spring-data-jpa 复杂查询的写法(包含or的查询)

记录一下,因为之前遇见的spring-data-jpa相关业务都是很简单的处理掉了。


场景如下:很简单的CMS常用查询,栏目下有多个子栏目,子栏目有包含内容。

public class Channel{
....
private String parentIds;//所有的父节点,简化查询策略 例如 0,1,11, 
private List<Channel> 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<Content> getContentListPaged(final Integer channelId,final Collection<SearchFilter> filters,int pageNumber, int pageSize){
		
		return contentDao.findAll(new Specification<Content>(){
			
			@Override
			public Predicate toPredicate(Root<Content> root,
					CriteriaQuery<?> query, CriteriaBuilder builder) {

				//path转化
				List<Predicate> orPredicates = Lists.newArrayList();
				
				Path<String> idPath = root.get("channel").get("id");
				Path<String> 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 ?



你可能感兴趣的:(spring)