Ответ 1
Per JB Nizet и spring -data documentation, вы должны использовать пользовательский интерфейс + репозиторий.
Создайте интерфейс с помощью метода:
public interface MyEntityRepositoryCustom {
List<User> findByFilterText(Set<String> words);
}
Создайте реализацию:
@Repository
public class MyEntityRepositoryImpl implements MyEntityRepositoryCustom {
@PersistenceContext
private EntityManager entityManager;
public List<User> findByFilterText(Set<String> words) {
// implementation below
}
}
Расширьте новый интерфейс в существующем интерфейсе репозитория:
public interface MyEntityRepository extends JpaRepository<MyEntity, Long>, MyEntityRepositoryCustom {
// other query methods
}
Наконец, вызовите метод где-то еще:
dao.findByFilterText(new HashSet<String>(Arrays.asList(filterText.split(","))));
Реализация запроса
Ваш метод создания переменной sql
, а именно путем конкатенации некоторых строк в запрос, является плохим. Не делайте этого.
word
, который вы конкатенируете, должен быть действительным идентификатором JPQL, а именно :
, за которым следует начало java-идентификатора, необязательно сопровождаемый некоторой частью java identifier part. Это означает, что если ваш CSV содержит foo bar,baz
, вы попытаетесь использовать foo bar
в качестве идентификатора, и вы получите исключение.
Вместо этого вы можете использовать CriteriaBuilder
, чтобы построить запрос безопасным способом:
public List<User> findByFilterText(Set<String> words) {
CriteriaBuilder cb = entityManager.getCriteriaBuilder();
CriteriaQuery<User> q = cb.createQuery(User.class);
Root<User> user = q.from(User.class);
Path<String> namePath = user.get("name");
Path<String> userTypeClassTypeDisplayName =
user.get("userType").get("classType").get("displayName");
Path<String> userTypeModel = user.get("userType").get("model");
List<Predicate> predicates = new ArrayList<>();
for(String word : words) {
Expression<String> wordLiteral = cb.literal(word);
predicates.add(
cb.or(
cb.like(cb.lower(namePath), cb.lower(wordLiteral)),
cb.like(cb.lower(userTypeClassTypeDisplayName),
cb.lower(wordLiteral)),
cb.like(cb.lower(userTypeModel), cb.lower(wordLiteral))
)
);
}
q.select(doc).where(
cb.and(predicates.toArray(new Predicate[predicates.size()]))
);
return entityManager.createQuery(q).getResultList();
}