根据JB Nizet和spring-data documentation,您应该使用自定义接口存储库实现.
使用方法创建接口:
public interface MyEntityRepositoryCustom {
List findByFilterText(Set words);
}
创建一个实现:
@Repository
public class MyEntityRepositoryImpl implements MyEntityRepositoryCustom {
@PersistenceContext
private EntityManager entityManager;
public List findByFilterText(Set words) {
// implementation below
}
}
扩展现有Repository接口中的新接口:
public interface MyEntityRepository extends JpaRepository, MyEntityRepositoryCustom {
// other query methods
}
最后,在其他地方调用该方法:
dao.findByFilterText(new HashSet(Arrays.asList(filterText.split(","))));
查询实现
生成sql变量的方法,即将一些字符串连接到查询中是不好的.不要这样做.
你连接的单词必须是valid JPQL identifier,即a:后跟java identifier start,可选后跟一些java identifier part.这意味着如果你的CSV包含foo bar,baz,你将尝试使用foo bar作为标识符,你’我会得到一个例外.
您可以使用CriteriaBuilder以安全的方式构造查询:
public List findByFilterText(Set words) {
CriteriaBuilder cb = entityManager.getCriteriaBuilder();
CriteriaQuery q = cb.createQuery(User.class);
Root user = q.from(User.class);
Path namePath = user.get("name");
Path userTypeClassTypeDisplayName =
user.get("userType").get("classType").get("displayName");
Path userTypeModel = user.get("userType").get("model");
List predicates = new ArrayList<>();
for(String word : words) {
Expression 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();
}