Я пишу webapp используя Spring Data JPA на уровне persistence, более конкретно, мои 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
s, которые содержат именно те tagsToFilterBy
, другими словами, tagsToFilterBy
должны быть подмножеством Item.tags
.
Я знаю о 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 Collection описывается каждый из этих методов расширения.
Поэтому мне удалось написать сам. Я не говорю, что это красиво, но это самый красивый, я мог бы прийти с:
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()) }
Это в основном происходит через теги и проверяет, является ли он элементом тегов или нет.