目前我一直在使用以下 Spring JPA Repository 基本自定义查询,它工作正常,
@Query("SELECT usr FROM User usr WHERE usr.configurable = TRUE "
+ "AND (" +
"lower(usr.name) like lower(:filterText) OR lower(usr.userType.classType.displayName) like lower(:filterText) OR lower(usr.userType.model) like lower(:filterText)"
+ ")"
+ "")
public List<User> findByFilterText(@Param("filterText") String filterText, Sort sort);
当过滤器文本将是逗号分隔值时,我需要修改此查询。但按照以下方式,它将是一个动态查询,我该如何执行它。
我需要构建动态查询,
String sql = "SELECT usr FROM User usr WHERE usr.configurable = TRUE";
for(String word : filterText.split(",")) {
sql += " AND (lower(usr.name) like lower(:" + word + ") OR lower(usr.userType.classType.displayName) like lower(:" + word + ") OR lower(usr.userType.model) like lower(:" + word + "))";
}
最佳答案
JB Nizet 和 spring-data documentation ,您应该使用自定义接口(interface)+存储库实现。
使用以下方法创建接口(interface):
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
}
}
在现有的存储库接口(interface)中扩展新接口(interface):
public interface MyEntityRepository extends JpaRepository<MyEntity, Long>, MyEntityRepositoryCustom {
// other query methods
}
最后,在其他地方调用该方法:
dao.findByFilterText(new HashSet<String>(Arrays.asList(filterText.split(","))));
查询实现
您生成sql
变量的方法,即通过将一些字符串连接到查询中,是不好的。 不要这样做。
您要连接的单词
必须是valid JPQL identifier ,即 :
后跟 java identifier start ,可选地后跟一些 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();
}
关于java - Spring JPA Repository动态查询,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/43752080/