Jpa Specification来查找字段值的子集
我正在持久层上使用Spring Data JPA编写JpaSpecificationExecutor
应用程序,更具体地说,我的DAO扩展了JpaSpecificationExecutor
接口,所以我能够实现某种过滤器; 想象具有多个属性的Item
列表(为了清楚起见,我省略了注释和其他元数据):
data class Item(var tags: MutableList<String>)
在我的服务层上,我的过滤方法如下所示:
fun findBy(tagsToFilterBy: List<String>): List<Items> { return dao.findAll { root, query, builder -> builder.//?? } }
我想要实现的是仅检索包含完全tagsToFilterBy
,换句话说, tagsToFilterBy
应该是tagsToFilterBy
一个子集。
我知道isMember(...)
方法,但我认为它的使用不会很令人愉快,因为它只接受一个“实体”在调用。 你可以给我一些建议吗?
我的另一个问题是,是否可以直接使用用户输入,比如builder.like(someExpression, inputFromUser)
或者我必须把它放在builder.parameter(...)
然后query.setParameter(...)
。
谢谢你的任何想法
一种方法是使用过滤器并测试每个元素来查看您的过滤器列表是否包含它。
val result = dao.filter { tagsToFilterBy.contains(it.tag) }
为了加快速度,你可以强制排序你的筛选器列表,也许可以使用binarySearch
,但性能改进(或不)将取决于筛选器列表的大小。 例如,假设tagsToFilterBy
被排序,那么:
val result2 = dao.filter { tagsToFilterBy.binarySearch(it.tag) >= 0 }
Kotlin集合页面描述了每个扩展方法。
所以我设法自己写。 我并不是说它很漂亮,但它是最漂亮的一个,我可以跟着来:
dao.findAll { root, query, builder -> val lst = mutableListOf<Predicate>() val tagsPath = root.get<List<Tag>>("tags") tagsToFilterBy.forEach { lst.add(cb.isMember(it, tagsPath)) } cb.or(*lst.toTypedArray()) }
这基本上是通过给定的标签,并检查它是否是标签的成员。