Hibernate Criteria查询:Projection与restriction冲突问题
解决Hibernate Criteria中Projection与txnType Restriction的冲突问题
嘿,这个问题我之前在项目里也碰到过,咱们一步步拆解原因和解决方案~
首先得明确冲突的核心:当你用Projection指定查询列时,Hibernate对实体字段的解析逻辑会发生变化,常见的报错场景和对应解决方法如下:
1. 检查实体字段映射是否正确
最基础的排查:先确认你的实体类(比如Transaction)里的txnType属性是否正确映射到数据库表的对应列。比如:
- 有没有加
@Column注解?如果数据库列名是TXN_TYPE,实体属性名是txnType,要确保注解配置匹配:@Column(name = "TXN_TYPE") private String txnType; - 有没有拼写错误?比如把
txnType写成了txnTyep,这种低级错误很容易导致Hibernate找不到字段。
2. 使用别名时,Restriction要对应别名引用
如果你给实体加了查询别名(比如关联查询时),一定要在Restriction里用别名前缀引用字段,否则Hibernate会解析失败:
// 错误示例:给实体加了别名,但Restriction里直接用属性名 Criteria criteria = session.createCriteria(Transaction.class, "t"); criteria.add(Restrictions.eq("txnType", "DEBIT")); // 这里会报错 // 正确示例:用别名前缀引用字段 criteria.add(Restrictions.eq("t.txnType", "DEBIT"));
3. 聚合/分组场景下,需将txnType加入Projection
如果你用了group by或者聚合函数(比如count、sum),Hibernate要求非聚合字段必须出现在Projection中,否则会触发SQL语法错误或者Hibernate解析异常。比如你要按txnType分组同时过滤它:
ProjectionList projectionList = Projections.projectionList(); projectionList.add(Projections.property("id"), "id"); projectionList.add(Projections.property("amount"), "amount"); // 必须把txnType加入Projection,否则group by或过滤时会报错 projectionList.add(Projections.property("txnType"), "txnType"); criteria.setProjection(projectionList); criteria.add(Restrictions.eq("txnType", "DEBIT")); criteria.add(Projections.groupProperty("txnType"));
4. SQL投影场景下,字段名要匹配数据库列
如果你用了Projections.sqlProjection(直接写SQL语句指定查询列),那么Restriction里如果用原生SQL条件,要匹配数据库列名,而不是实体属性名:
// 用SQL投影指定查询列 projectionList.add(Projections.sqlProjection( "ID, AMOUNT", new String[]{"id", "amount"}, new Type[]{LongType.INSTANCE, DoubleType.INSTANCE} )); // 用SQL Restriction时,要写数据库列名TXN_TYPE,不是实体属性txnType criteria.add(Restrictions.sqlRestriction("TXN_TYPE = ?", "DEBIT", StringType.INSTANCE));
完整正确示例
给你一个可直接参考的代码片段(假设实体类Transaction映射正确):
Session session = sessionFactory.getCurrentSession(); Criteria criteria = session.createCriteria(Transaction.class); // 定义要查询的列 ProjectionList projectionList = Projections.projectionList(); projectionList.add(Projections.property("id"), "id"); projectionList.add(Projections.property("amount"), "amount"); // 添加过滤条件 criteria.add(Restrictions.eq("txnType", "DEBIT")); // 设置投影和结果转换器(如果需要转DTO) criteria.setProjection(projectionList); criteria.setResultTransformer(Transformers.aliasToBean(TransactionDTO.class)); // 执行查询 List<TransactionDTO> results = criteria.list();
其中TransactionDTO需要和投影的字段对应:
public class TransactionDTO { private Long id; private Double amount; // 投影里加了txnType的话,这里也要对应添加属性和setter // private String txnType; // getters and setters }
内容的提问来源于stack exchange,提问作者Abhishek Patil
相关产品推荐
相关产品推荐

