2017-09-05 50 views
0

我写持久层上使用Spring数据JPA web应用程序,更具体地说,我的DAO扩展JpaSpecificationExecutor接口,所以我能够实现某种过滤器;想象有几个属性的Item的名单(我省略为清楚起见,注释和其他元数据):JPA规范找到字段的值的子集

data class Item(var tags: MutableList<String>) 

在我的业务层,我的滤波方法是这样的:

fun findBy(tagsToFilterBy: List<String>): List<Items> { 
    return dao.findAll { root, query, builder -> 
     builder.//?? 
    } 
} 

我想要什么实现的是只检索Item包含正是tagsToFilterBy S,换句话说,tagsToFilterBy应该是Item.tags一个子集。

我知道isMember(...)方法,但我认为它的用法只接受单一的“实体”在呼叫不会很宜人,许多标签。你能帮我一些建议吗?

我的另一个问题是,直接使用用户输入是否安全,比如builder.like(someExpression, inputFromUser)或者我必须把它放在builder.parameter(...)然后query.setParameter(...)

谢谢你的任何想法

回答

0

的一种方法是使用过滤器和测试每个元素,看看您的过滤器列表中包含它。

val result = dao.filter { tagsToFilterBy.contains(it.tag) } 

加快步伐,你可能会迫使排序过滤器列表,也许使用binarySearch,但性能改善(与否)将取决于筛选器列表的大小。例如,假定tagsToFilterBy进行排序,然后:

val result2 = dao.filter { tagsToFilterBy.binarySearch(it.tag) >= 0 } 

Kotlin Collection页描述了每个的这些扩展方法。

+0

我忘记提到的问题,我可能有更多的属性来过滤,这就是为什么我需要使用'规格' –

+0

我发布了代码,解决了我的问题,随时看看。 –

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()) 
} 

这基本上是通过给定的标签去,并检查它是否是标签或不是其成员。