将条件 API + JPA 规范与 IN 表达式和 Spring 引导一起使用
Using Criteria API + JPA Specifications with IN Expression and Spring Boot
我在 Kotlin 中实现了 https://www.baeldung.com/spring-data-criteria-queries#specifications 中的示例。为此,我扩展了接口存储库:
interface BookRepository : JpaRepository<Book, String>, JpaSpecificationExecutor<Book>
并在 Kotlin 中创建了两个方法以创建规范实例:
fun hasAuthor(author: String?): Specification<Book?>? {
return Specification<Book?> { book, cq, cb -> cb.equal(book.get<Any>("author"), author) }
}
fun titleContains(title: String): Specification<Book?>? {
return Specification<Book?> { book, cq, cb: CriteriaBuilder -> cb.like(book.get("title"), "%$title%") }
}
现在,当作者和标题只是一个字符串时,我可以按预期简单地执行此操作:
fun getFilteredBooks(parameters: BookFilterParameters): List<Books> {
return bookRepository.findAll(where(hasAuthor(parameters.bookName)).and(hasTitle(parameters.title)))
}
现在考虑 author 不仅仅是一个字符串,而是一个实体:
@Entity
@Table(
name = "book",
schema = "book"
)
data class Book(
@Id
var id: String,
@ManyToOne(cascade = [CascadeType.DETACH, CascadeType.PERSIST, CascadeType.REFRESH, CascadeType.MERGE])
@JoinColumn(name="author")
var author: Author? = null,
@Column
var title: String? = null
)
...
此外,我想像这样比较整个作者列表:
fun hasAuthors(authorsFirstName: List<String>): Specification<Book?>? {
return Specification<Book?> { book, cq, cb -> cb.`in`(book.get<Any>("author.firstName")).value(authorsFirstName) }
}
但是,这会导致出现以下错误消息:
Unable to locate Attribute with the the given name [author.firstName] on this ManagedType [de.bookstore.Book]
如何正确定义请求?
尝试
fun hasAuthors(authorsFirstName: List<String>): Specification<Book?>? {
return Specification<Book?> {
book, cq, cb -> cb.in(book
.join<Book, Author>("book")
.get<Any>("firstName")).value(authorsFirstName)
}
}
我在 Kotlin 中实现了 https://www.baeldung.com/spring-data-criteria-queries#specifications 中的示例。为此,我扩展了接口存储库:
interface BookRepository : JpaRepository<Book, String>, JpaSpecificationExecutor<Book>
并在 Kotlin 中创建了两个方法以创建规范实例:
fun hasAuthor(author: String?): Specification<Book?>? {
return Specification<Book?> { book, cq, cb -> cb.equal(book.get<Any>("author"), author) }
}
fun titleContains(title: String): Specification<Book?>? {
return Specification<Book?> { book, cq, cb: CriteriaBuilder -> cb.like(book.get("title"), "%$title%") }
}
现在,当作者和标题只是一个字符串时,我可以按预期简单地执行此操作:
fun getFilteredBooks(parameters: BookFilterParameters): List<Books> {
return bookRepository.findAll(where(hasAuthor(parameters.bookName)).and(hasTitle(parameters.title)))
}
现在考虑 author 不仅仅是一个字符串,而是一个实体:
@Entity
@Table(
name = "book",
schema = "book"
)
data class Book(
@Id
var id: String,
@ManyToOne(cascade = [CascadeType.DETACH, CascadeType.PERSIST, CascadeType.REFRESH, CascadeType.MERGE])
@JoinColumn(name="author")
var author: Author? = null,
@Column
var title: String? = null
)
...
此外,我想像这样比较整个作者列表:
fun hasAuthors(authorsFirstName: List<String>): Specification<Book?>? {
return Specification<Book?> { book, cq, cb -> cb.`in`(book.get<Any>("author.firstName")).value(authorsFirstName) }
}
但是,这会导致出现以下错误消息:
Unable to locate Attribute with the the given name [author.firstName] on this ManagedType [de.bookstore.Book]
如何正确定义请求?
尝试
fun hasAuthors(authorsFirstName: List<String>): Specification<Book?>? {
return Specification<Book?> {
book, cq, cb -> cb.in(book
.join<Book, Author>("book")
.get<Any>("firstName")).value(authorsFirstName)
}
}