首页 > 代码库 > 关于hibernate 多实体(多表)连接查询映射到实体的讨论

关于hibernate 多实体(多表)连接查询映射到实体的讨论

前提表与实体信息:

<script src="https://code.csdn.net/snippets/424098.js" type="text/javascript"></script>
<script src="https://code.csdn.net/snippets/424105.js" type="text/javascript"></script>
<script src="https://code.csdn.net/snippets/424174.js" type="text/javascript"></script>

在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这个类的错,它和已经映射的实体类还是有区别的,很多人由于不加包名,误认为这样的方法不可行,

这是错误的。

以上是个人的理解,如果有错误,请大家一定指正,如有更好的处理方式,也期待电脑前的你,分享出来吧!