如何将含子查询的SQL转换为Hibernate Criteria查询?
Hibernate Criteria实现带子查询的SQL转换
原SQL核心逻辑
你需要实现的是:筛选出service_code匹配指定模式的记录,并且仅保留每个service_code对应**最新S_STARTDATE**的条目,最后按service_code和S_STARTDATE排序。
完整Criteria实现代码
结合你的实体类和需求,修改后的代码如下:
// 1. 创建主Criteria,关联实体类 Criteria criteria = this.getSession().createCriteria(BillingProductBaseView.class, "vsic"); // 2. 处理ids参数:多个serviceCode的like条件(OR逻辑) if (!ids.isEmpty()) { Disjunction disjunction = Restrictions.disjunction(); for (String id : ids) { disjunction.add(Restrictions.like("vsic.serviceCode", id)); } criteria.add(disjunction); } // 3. 构建子查询:查询每个serviceCode对应的最大sStartDate DetachedCriteria maxStartDateSubquery = DetachedCriteria.forClass(BillingProductBaseView.class, "sub") .setProjection(Projections.max("sub.sStartDate")) .add(Restrictions.eqProperty("sub.serviceCode", "vsic.serviceCode")); // 关联主查询的serviceCode // 4. 添加子查询条件:主查询的sStartDate等于子查询的最大值 criteria.add(Restrictions.eqProperty("vsic.sStartDate", maxStartDateSubquery)); // 5. 设置投影(按需选择需要返回的字段) criteria.setProjection(Projections.projectionList() .add(Projections.property("vsic.serviceCode"), "serviceCode") .add(Projections.property("vsic.serviceVersion"), "serviceVersion") .add(Projections.property("vsic.sStartDate"), "sStartDate")); // 6. 设置结果转换器,将投影结果映射到实体类 criteria.setResultTransformer(Transformers.aliasToBean(BillingProductBaseView.class)); // 7. 添加排序规则 criteria.addOrder(Order.asc("vsic.serviceCode")); criteria.addOrder(Order.asc("vsic.sStartDate")); // 8. 执行查询 List<BillingProductBaseView> billingProductOfferingViewList = criteria.list();
关键部分说明
- 多条件OR处理:原代码循环添加
Restrictions.like会生成多个AND条件,不符合需求,改用Disjunction实现多个LIKE的OR逻辑。 - 子查询实现:用
DetachedCriteria构建子查询,通过eqProperty关联主查询和子查询的serviceCode,确保每个serviceCode取自身的最大S_STARTDATE。 - 投影与结果转换:明确指定需要返回的字段,避免查询冗余数据,
Transformers.aliasToBean用于将投影结果映射到实体类(注意实体类字段名要和投影别名一致)。 - 排序:添加
Order.asc实现原SQL的排序规则。
注意事项
如果你的实体类中包含v_end_date对应的字段(比如vEndDate),只需在投影中添加Projections.property("vsic.vEndDate"), "vEndDate"即可。
内容的提问来源于stack exchange,提问作者batman35
相关产品推荐
相关产品推荐

