jparepository查询所有_Spring JPA Repository动态查询

Currently I have been using following Spring JPA Repository base custom query and it works fine,

@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 findByFilterText(@Param("filterText") String filterText, Sort sort);

I need to modify this query when filter text going to be a comma separated value. But as following manner it will be a dynamic query and how can I execute it.

Dynamic query I need to build,

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 + "))";

}

解决方案

Per JB Nizet and the spring-data documentation, you should use a custom interface + repository implementation.

Create an interface with the method:

public interface MyEntityRepositoryCustom {

List findByFilterText(Set words);

}

Create an implementation:

@Repository

public class MyEntityRepositoryImpl implements MyEntityRepositoryCustom {

@PersistenceContext

private EntityManager entityManager;

public List findByFilterText(Set words) {

// implementation below

}

}

Extend the new interface in your existing Repository interface:

public interface MyEntityRepository extends JpaRepository, MyEntityRepositoryCustom {

// other query methods

}

Finally, call the method somewhere else:

dao.findByFilterText(new HashSet(Arrays.asList(filterText.split(","))));

Query implementation

Your method of producing the sql variable, namely by concatenating some strings into the query is bad. Do not do this.

The word which you are concatenating must be a valid JPQL identifier, namely a : followed by a java identifier start, optionally followed by some java identifier part. This means that if your CSV contains foo bar,baz, you will attempt to use foo bar as an identifier and you'll get an exception.

You can instead use CriteriaBuilder to construct the query in a safe way:

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();

}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值