JPA排序中的join排序及case when的使用

最近项目中开始使用JPA,使用过程中有两个排序场景遇到的问题,在此将问题及解决方法作一个记录。

先抛出问题:

  1. model类A中包含Set<B>成员,即一对多关系,要求查询A的时候按A包含的B对象个数来排序。
  2. model类A中包含一个String s字段,该字段在数据库中保存的是"00/01/11"这样的数字字符串数据,但是在界面显示的是中文描述信息,这个中文描述信息与数据库中的数字字符串一一对应,要求按这个字段排序。

 

这里把类示例代码贴出来:

class A {

    private String id;



    @OneToMany

    private Set<B> objBs;

}

class B {

    private String id;



    @ManyToOne

    private A a;

}

问题1解决方法:

Expression<Integer> sum = cb.count(root.join("objBs", JoinType.LEFT)).as(Integer.class);
  					
if (StringUtils.equals("DESC", localOrder)) {
   return query.where(predicates.toArray(new Predicate[predicates.size()])).								    
           groupBy(root.get("id").as(String.class)).orderBy(cb.desc(sum)).getRestriction();
 }
return query.where(predicates.toArray(new Predicate[predicates.size()])).
  		    groupBy(root.get("id").as(String.class)).orderBy(cb.asc(sum)).getRestriction();

问题2解决方法:

Expression<String> sStr = cb.selectCase()
	.when(cb.equal(root.get("s").as(String.class), "00"), 
			Constants.pluginTypeMap.get("00"))
	.when(cb.equal(root.get("s").as(String.class), "01"), 
			Constants.pluginTypeMap.get("01"))
	.when(cb.equal(root.get("s").as(String.class), "10"), 
			Constants.pluginTypeMap.get("10"))
	.when(cb.equal(root.get("s").as(String.class), "11"), 
			Constants.pluginTypeMap.get("11"))
	.when(cb.equal(root.get("s").as(String.class), "12"), 
			Constants.pluginTypeMap.get("12"))
	.when(cb.equal(root.get("s").as(String.class), "13"), 
			Constants.pluginTypeMap.get("13")).as(String.class);
								
if (StringUtils.equals("DESC", localOrder)) {
  	return query.where(predicates.toArray(new Predicate[predicates.size()]))
  								.orderBy(cb.desc(sStr)).getRestriction();
 }
return query.where(predicates.toArray(new Predicate[predicates.size()]))
  							.orderBy(cb.asc(sStr)).getRestriction();

这样写以后报错:

at org.hibernate.jpa.criteria.expression.SearchedCaseExpression.render(SearchedCaseExpression.java:125)

根据报错的位置跟踪到源码

org.hibernate.jpa.criteria.expression.SearchedCaseExpression.render(RenderingContext)里面第二个caseStatement:

public String render(RenderingContext renderingContext) {
	StringBuilder caseStatement = new StringBuilder( "case" );
	for ( WhenClause whenClause : getWhenClauses() ) {
		caseStatement.append( " when " )
			.append( ( (Renderable) whenClause.getCondition() ).render( renderingContext ) )
			.append( " then " )
			.append( ( (Renderable) whenClause.getResult() ).render( renderingContext ) );
		}
		caseStatement.append( " else " )
				.append( ( (Renderable) getOtherwiseResult() ).render( renderingContext ) )
				.append( " end" );
		return caseStatement.toString();
	}

猜想是缺少一个otherWise(),于是改成:

Expression<String> sStr = cb.selectCase()
	.when(cb.equal(root.get("s").as(String.class), "00"), 
			Constants.pluginTypeMap.get("00"))
	.when(cb.equal(root.get("s").as(String.class), "01"), 
			Constants.pluginTypeMap.get("01"))
	.when(cb.equal(root.get("s").as(String.class), "10"), 
			Constants.pluginTypeMap.get("10"))
	.when(cb.equal(root.get("s").as(String.class), "11"), 
			Constants.pluginTypeMap.get("11"))
	.when(cb.equal(root.get("s").as(String.class), "12"), 
			Constants.pluginTypeMap.get("12"))
	.when(cb.equal(root.get("s").as(String.class), "13"), 
			Constants.pluginTypeMap.get("13")).
        .otherWise("").as(String.class);
								
if (StringUtils.equals("DESC", localOrder)) {
  	return query.where(predicates.toArray(new Predicate[predicates.size()]))
  								.orderBy(cb.desc(sStr)).getRestriction();
 }
return query.where(predicates.toArray(new Predicate[predicates.size()]))
  							.orderBy(cb.asc(sStr)).getRestriction();

bingo!问题解决!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值