2019独角兽企业重金招聘Python工程师标准>>>
场景如下:很简单的CMS常用查询,栏目下有多个子栏目,子栏目有包含内容。
public class Channel{
....
private String parentIds;//所有的父节点,简化查询策略 例如 0,1,11,
private List channels = Lists.newArrayList(); //所有的儿子栏目
...
}
public class Content{
private Channel channel; //属于哪个栏目
}
所以比如有如下结构时:栏目A下有两个子栏目B,C;这三个栏目下都有各自的内容, 那么当查询A下的内容时,肯定也是要包含B,C栏目下的内容。
比如说A栏目的id是 10 ,再加上别的查询条件的话, 也就是说 sql 语句肯定是类似:
select * from Content as s where (s.channel.id = 10 or s.channel.parentIds like '%,10,%') and s.yyy = 'xxxxx' and s.xxx = 'yyyy';
想来想去发现实在没有简单的办法做or查询之后跟动态的and查询参数,好像只能自己构造,所以在此记录一下,避免忘记。
此处动态的and 查询条件构造是使用了springside的方法。并且我不知道这样的构造方法是不是spring-data-jpa的标准做法,如果不是,请指正
/**
* 查询某个栏目下的所有文章,并且分页。
*
* 如该栏目下有子栏目,则需要一起显示
*
* @param channelId 栏目id
* @param searchParams
* @param pageNumber
* @param pageSize
* @return
*/
public Page getContentListPaged(final Integer channelId,final Collection filters,int pageNumber, int pageSize){
return contentDao.findAll(new Specification(){
@Override
public Predicate toPredicate(Root root,
CriteriaQuery> query, CriteriaBuilder builder) {
//path转化
List orPredicates = Lists.newArrayList();
Path idPath = root.get("channel").get("id");
Path parentIdsPath = root.get("channel").get("parentIds");
Predicate p1 = builder.equal(root.get("channel").get("id"), channelId);
orPredicates.add(builder.or(p1));
Predicate p2 = builder.like((Path)root.get("channel").get("parentIds"), "%," + channelId + ",%");
orPredicates.add(builder.or(p2));
//以下是springside3提供的方法
Predicate o = DynamicSpecifications.bySearchFilter(filters, Content.class).toPredicate(root, query, builder);
Predicate p = builder.or(orPredicates.toArray(new Predicate[orPredicates.size()]));
query.where(p,o);
return null;
}
}, new PageRequest(pageNumber - 1, pageSize));
}
实际查询的输出sql如下,where之前省略:
where
content0_.channel_id=channel1_.id
and (
content0_.channel_id=21
or channel1_.parentIds like ?
)
and (
content0_.title like ?
) limit ?
另一个使用案例:
前端返回的查询结构:{"字段名1":"字段值1","字段名2":"字段值2"}
Sort sort = new Sort(Sort.Direction.DESC, "id");
Pageable pageable = new PageRequest(page<0?0:page, size<0?1:size, sort);
if(filters != null){
JSONObject params = JSON.parseObject(filters);
Set keys = params.keySet();
if(keys.size() > 0){
Specification spec = new Specification() {
public Predicate toPredicate(Root root, CriteriaQuery> query, CriteriaBuilder cb) {
List andPredicates = Lists.newArrayList();
for(String key : keys){
if(StringUtils.isNotBlank(params.getString(key)))andPredicates.add(cb.like(root.get(key),"%"+params.getString(key)+"%"));
}
Predicate p = cb.and(andPredicates.toArray(new Predicate[andPredicates.size()]));
query.where(p);
return null;
}
};
return logViewManager.findAll(spec,pageable);
}
}