论坛首页 Java版 Hibernate

hibernate继承关系的性能

浏览 2601 次
精华帖 (0) :: 良好帖 (0) :: 新手帖 (0) :: 隐藏帖 (0)
作者 正文
最后更新时间:2008-04-11
最近做一个申请单流程控制的东东,里面有很多不同的申请单,每张单有10-30个要填写的地方,但都有一些共同的地方,如申请人、申请日期等。我的解决方案是把共同点拿出来建一张表作为父表,其他每张单一个表做为子表,通过主键关联确定申请单的类型,但这样查询的时候总会join所有的表,使得性能有问题,尤其在子表多的时候。我的另一个想法是在父表中添加一个type栏位,先在父表中查出是哪张子表,然后查出对应的申请单信息,这样无论多少张子表都是2步查询,相当于为所有子表建一个索引。但hibernate的继承似乎不支持这种方式,或者二级缓存可以解决这个问题?请达人解惑!
   
最后更新时间:2008-04-11
我们项目当中也遇到这类似的问题.
用BaseInfo将所有的公用信息字段都抽取出来.
然后针对不同的种类设计单独的类. 
在每个单独的类里面聚合一个BaseInfo. 不过在处理级联关系的时候要特别小心.
   
0 请登录后投票
最后更新时间:2008-04-11
谢谢lsk,但我希望能够保留继承关系,因为我需要在同一个方法中根据申请单号取出对应的所有信息。委托能够完成,但需要另一个参数表示要查询的子类,那样的话我需要写上一堆的if-else,但继承可以很简洁的处理这中情况,所以我想知道有没有保留继承关系同时性能不差的方法。
   
0 请登录后投票
最后更新时间:2008-04-11
hibernate的继承关系,虽然更加完好的实现了"使以面向对象的方式思考持久化成为可能",然而我感觉很多同学在使用它的时候,仍旧在按照关系数据库的思维,在思考.
   
0 请登录后投票
最后更新时间:2008-04-11
xellos 写道
hibernate的继承关系,虽然更加完好的实现了"使以面向对象的方式思考持久化成为可能",然而我感觉很多同学在使用它的时候,仍旧在按照关系数据库的思维,在思考.

我覺得我的思考方式已經很“對象”了,也許你能幫我支出問題所在?
   
0 请登录后投票
最后更新时间:2008-04-12
我也遇到这样的问题了,希望尽快有一个最好的解决方案出来
   
0 请登录后投票
最后更新时间:2008-04-12
我觉得解决方法不应该在Hibernate上而应该在对象构建上
用一个父类描述所有的公共属性,子类对应每一张数据库中的表继承之

另外也可以从数据库设计上避免数据冗余
一句话就是要么在持久层端解决,要么在领域模型端解决,ORM只是一个桥梁
   
0 请登录后投票
最后更新时间:2008-04-14
lingzantia 写道
谢谢lsk,但我希望能够保留继承关系,因为我需要在同一个方法中根据申请单号取出对应的所有信息。委托能够完成,但需要另一个参数表示要查询的子类,那样的话我需要写上一堆的if-else,但继承可以很简洁的处理这中情况,所以我想知道有没有保留继承关系同时性能不差的方法。


但需要另一个参数表示要查询的子类:不懂什么意思。

hibernate取出的对象就是你需要查找的子类的类型

三种配置方式看你喜欢哪一种了,我喜欢一个父类、n个子类的方式,表的映射关系也是如此,使用discriminator的方式来配置
   
0 请登录后投票
最后更新时间:2008-04-14
majianshe 写道
lingzantia 写道
谢谢lsk,但我希望能够保留继承关系,因为我需要在同一个方法中根据申请单号取出对应的所有信息。委托能够完成,但需要另一个参数表示要查询的子类,那样的话我需要写上一堆的if-else,但继承可以很简洁的处理这中情况,所以我想知道有没有保留继承关系同时性能不差的方法。


但需要另一个参数表示要查询的子类:不懂什么意思。

hibernate取出的对象就是你需要查找的子类的类型

三种配置方式看你喜欢哪一种了,我喜欢一个父类、n个子类的方式,表的映射关系也是如此,使用discriminator的方式来配置


比如,有这样的地址请求:http://www.xxx.com/applicationsview?id=123&class=ABC
如果是用继承关系的话,那么我取得申请单信息就要这样:Application app = DAOFactory.getDAOFactory().getApplicationDAO().findByPK(new Long(request.getParameter("id"))); 这样就可以取得所有信息。
如果是用委托关系的话,那代码大致是这样:
if("ABC".equalse(request.getParameter(class))){
    ABC abc = DAOFactory.getDAOFactory().getABCDAO().findByPK(new Long(request.getParameter("id")));
}esle if("DEF".equalse(request.getParameter(class))){
    DEF def = DAOFactory.getDAOFactory().getABCDAO().findByPK(new Long(request.getParameter("id")));
} ......
当子类多的时候就是很长的一片if-else,我觉得继承关系的代码清爽一些,但是查询会join所有的表,所以想知道有没有更好的方法。
   
0 请登录后投票
最后更新时间:2008-04-14
lingzantia 写道
最近做一个申请单流程控制的东东,里面有很多不同的申请单,每张单有10-30个要填写的地方,但都有一些共同的地方,如申请人、申请日期等。我的解决方案是把共同点拿出来建一张表作为父表,其他每张单一个表做为子表,通过主键关联确定申请单的类型,但这样查询的时候总会join所有的表,使得性能有问题,尤其在子表多的时候。我的另一个想法是在父表中添加一个type栏位,先在父表中查出是哪张子表,然后查出对应的申请单信息,这样无论多少张子表都是2步查询,相当于为所有子表建一个索引。但hibernate的继承似乎不支持这种方式,或者二级缓存可以解决这个问题?请达人解惑!


hibernate 好像可以这样做,不过好像是混合使用Table Per Class Hierarchy 和<join>
比如A, B, C 三个类, A, 是B, C 的父类,同时有三个表, a, b, c,a表中有一个字段type, 对应b, c。
用下面方法可能可以做到你想要的结果
<class name="A" table="B">
    ...
   <discriminator column="type" type="string"/>
   <subclass name="B" discriminator-value="b">
      <join table="b">
      </join>
   <subclass>
   <subclass name="C" discriminator-value="c">
      <join table="c">
      </join>
   <subclass>
    ...
</class>


这种做法最终生成的sql,(以from B 为例)可能像下面这样:
select * from A left outer join B on A_id = B_id
还可以通过给<join> 增加fetch = “select” , 使得上面的sql 变为使用另外一个select 语句,而不是outer join。
   
0 请登录后投票
论坛首页 Java版 Hibernate

跳转论坛:
JavaEye推荐