关于hibernate 多实体(多表)连接查询映射到实体的讨论
前提表与实体信息:
在hibernate 查询中,我们经过遇到三种情况:
1、查询事个实体,如: select b from TableB b; 返回的LIst 中封装的是 实体TableB的实例。
2、查询单个属性,如: select b.id from TableB b; hibernate 返回的List 中封装的是ojbect对象。
3、当查询多于一个属性且又不是整个实体时,如:select b.id,b.mes from TableB b;返回的List中封装的是Object[]数组,也就是list是行数,object[]是一行里的列数。
这时我们就会有一个需求,怎么样把查询多个属性时的值赋到对象中,直接调用实体的get方法方便的取得属性值,很多人都会按最原始的,取得object[]后循环来取值,
这样处理就比较繁琐,使代码变得冗长,可读性就差了,维护也不方便。
下面我们看看hibernate 怎么实现我们的功能,如下:
比如我们查询TableA 的id,name,那么我们的TableA就要有拥有这两个参数的构造函数,如上面的代码片段第一部分。HQL写法为:
select new Table(ta.id,ta.name) from TableA ta; 这样hibernate返回的list中封装就是TableA对象。
当有多个表连接查询时,我们想把其他的表的属性也封装到对象里,其实是类似的,如我们想把tableB里的mes属性也映射到TableA里,这时,我们就要往类TableA里添加属性:mes ,并添加对应set,get方法,注意这个属性在TableA里是不存在的,所以要时行忽略映射到数据库的注解如下:
@Transient
private String mes;
添加查询时用到的构造函数:
public TableA(Long id,String name,String mes){
this.id = id;
this.name = name;
this.mes = mes;
}
现在我们看看HQL是怎么写的:select new TableA(ta.id,ta.name,tb.mes) from TableA ta,TableB tb where ta.relId=tb.id;
这样hibernate 返回的依然是我们想要的 List中封装的TableA对象。
这样做法,有个不好的地方就是一些临时的属性入侵到了TableA实体,如果加的属性越来越多,这样的实体会变的面目全非,所以我们看看下面更加幽雅的处理方式。
引入临时对象来存储 如上面代码段中的 实体TableC,HQL:
select new com.pt.test.TableC(ta.id,ta.name,tb.id,tb.mes) from TableA ta,TableB tb where ta.relId=tb.id;
这样我们返回的list里封装的就是TableC实体了。
注意:com.pt.test.TableC这里一定要加上包名,否则会报找不到TableC这个类的错,它和已经映射的实体类还是有区别的,很多人由于不加包名,误认为这样的方法不可行,
这是错误的。
以上是个人的理解,如果有错误,请大家一定指正,如有更好的处理方式,也期待电脑前的你,分享出来吧!