我正在使用Spring Data JPA在持久层上编写一个webapp,更具体地说,我的DAO扩展了JpaSpecificationExecutor
接口,因此我能够实现某种过滤器;想象具有多个属性的Item
列表(为了清楚起见,我省略了注释和其他元数据):
data class Item(var tags: MutableList<String>)
在我的服务图层上,我的过滤方法如下所示:
fun findBy(tagsToFilterBy: List<String>): List<Items> {
return dao.findAll { root, query, builder ->
builder.//??
}
}
我想要实现的只是检索仅包含Item
的{{1}},换句话说,tagsToFilterBy
应该是tagsToFilterBy
的子集。
我知道Item.tags
方法,但我认为它的使用对于很多标签来说并不是很愉快,因为它在接听时只接受单个“实体”。你能给我一些建议吗?
我的另一个问题是,是否可以直接使用用户输入,例如isMember(...)
,或者我必须将其放在builder.like(someExpression, inputFromUser)
然后builder.parameter(...)
。
感谢您的任何想法
答案 0 :(得分:0)
一种方法是使用过滤器并测试每个元素,看看你的过滤器列表是否包含它。
val result = dao.filter { tagsToFilterBy.contains(it.tag) }
要加快速度,您可以强制对筛选器列表进行排序,也可以使用binarySearch
,但性能提升(或不提高)取决于筛选器列表的大小。例如,假设tagsToFilterBy
已排序,则:
val result2 = dao.filter { tagsToFilterBy.binarySearch(it.tag) >= 0 }
Kotlin Collection页面描述了这些扩展方法。
答案 1 :(得分:0)
所以我设法自己写。我不是说它很漂亮,但它是最漂亮的,我可以带来:
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())
}
这基本上是通过给定的标签,并检查它是否是标签的成员。