Hibernate criteria 混合sql语句多表关联时查询注意事项
直接进入正题
假设有一个实体类
/**
* 产品分类
*/
public class ProductType{
@Id
private String no;//编号
private String name;//名称
}
/**
* 产品
*/
public class Product{
@Id
private String no;//编号
private String name;//名称
private ProductType productType;
//...省略setter和getter方法
}
假设:ProductType 有如下数据:
no name
1 产品分类1
2 产品分类2
3 产品分类3
假设:Product 有如下数据:
no name productTypeNo
1000 产品一 1
1001 产品一 1
1003 产品二 2
1004 产品二 2
1005 产品三 3
使用场景:需要产品编号按连号显示:
1000-1002 产品一 产品分类1
1003-1004 产品二 产品分类2
1005-1005 产品三 产品分类3
以下是Criteria查询实现
Criteria criteria = session.createCriteria(Product.class,"p");
ProjectionList plist = Projections.projectionList();
plist.add(Projections.sqlProjection("min(no) || '-' || max(no)",new String[]{"no"},new Type[]{StringType.INSTANCE}))
.add(Projections.groupProperty("name"))
.add(Projections.groupProperty("ptype.name").as("productTypeName"));
criteria.setProjection(plist);
criteria.list();
注意事项如下:
1、由于需要获取productType中的属性,也就是需要联合查询,所以必须执行criteria查询是必须指定criteria.createAlias("productType","ptype");
2、由于执行SQL语句,而该查询中两个实体中都含有相同的属性no,所以必须指定no所属实例,上面红色部分必须更改为"min({alias}.no) || '-' || max({alias}.no)"
程序最终实现应该如下:
Criteria criteria = session.createCriteria(Product.class,"p");
ProjectionList plist = Projections.projectionList();
criteria.createAlias("productType","ptype");
plist.add(Projections.sqlProjection("min({alias}.no) || '-' || max({alias}.no)",new String[]{"no"},new Type[]{StringType.INSTANCE}))
.add(Projections.groupProperty("name"))
.add(Projections.groupProperty("ptype.name").as("productTypeName"));
criteria.setProjection(plist);
criteria.list();
总结:
1、Criteria 查询,需要获取非关联字段信息时,必须创建关联表criteria.createAlias("productType","ptype");
2、Criteria 查询,主表和关联表有相同数据库字段,且需要使用原始SQL语句时,必须指定别名,否则将无法找到指定列,而报“未明确指定列”的错误
min({alias}.no) || '-' || max({alias}.no)中{alias}会在运行时由Hibernate自动指定。