2017-09-05 45 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()) 
} 

這基本上是通過給定的標籤去,並檢查它是否是標籤或不是其成員。