本站首页    管理页面    写新日志    退出


«November 2025»
1
2345678
9101112131415
16171819202122
23242526272829
30


公告
 本博客在此声明所有文章均为转摘,只做资料收集使用。

我的分类(专题)

日志更新

最新评论

留言板

链接

Blog信息
blog名称:
日志总数:1304
评论数量:2242
留言数量:5
访问次数:7659741
建立时间:2006年5月29日




[Hibernate]在hibernate的对象关联中慎用outer-join属性值
软件技术

lhwork 发表于 2006/12/22 17:03:51

outer-join属性在hibernate表示迫切左外连接检索。  在xdoclet生成hibernate的hbm文件的时候,对持久化对象的关联对象(包括one-to-one,one-to-many,many- to-one,many-to-many等等),如果不指定outer-join的值的话,默认值为outer-join=auto。  然而,在使用过程中,我发现,对于outer-join=auto的情况,经常会发生错误。比如说many-to-one、one-to-many的关联 对象无法加载(对于集合已设定lazy=false,采用立即检索,理论上说与outer-join=auto联合应该能立即加载关联对象),当时没做总 结,具体在什么条件下产生问题我已经忘了,不过根源可能跟我下面想要说的问题的根源一致。  在这里主要想说得是针对many-to-many中outer-join取值不同所导致的一些问题,发在这里,权作备忘。系统使用的hibernate版本是3.0.3  先看看下面一个有意思的例子(从hbm文件可以看出模型结构,我就不贴了,dao,manager之类的也不贴了,这些都不是主要问题,数据库事务是在manager类中实现的)  TestRange.hbm.xml文件:  <?xml version="1.0" encoding="UTF-8"?>  <!DOCTYPE hibernate-mapping SYSTEM "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">  <hibernate-mapping default-cascade="none" auto-import="true">  <class node="testRange" name="application.model.TestRange" table="t_testrange" dynamic-update="false" dynamic-insert="false" select-before-update="false" optimistic-lock="version" mutable="true" polymorphism="implicit" batch-size="1">  <id node="id" name="id" type="java.lang.Long" unsaved-value="null">  <column name="testrange_id"/>  <generator class="native">  <!--  To add non XDoclet generator parameters, create a file named  hibernate-generator-params-TestRange.xml  containing the additional parameters and place it in your merge dir.  -->  </generator>  </id>  <property node="name" name="name" type="string" update="true" insert="true" access="property" not-null="false" unique="false">  <column name="name" length="50"/>  </property>  <!--  To add non XDoclet property mappings, create a file named  hibernate-properties-TestRange.xml  containing the additional properties and place it in your merge dir.  -->  <joined-subclass name="application.model.TestGroup" table="t_testgroup" dynamic-update="false" dynamic-insert="false">  <key column="testrange_id"/>  <set node="." lazy="false" name="testSet" table="t_tgroup_trange" inverse="false" cascade="save-update" sort="unsorted" batch-size="1" outer-join="auto">  <key column="testgroup_id">  </key>  <many-to-many node="testRange" embed-xml="true" class="application.model.TestRange" column="testrange_id" outer-join="auto"/>  </set>  </joined-subclass>  <joined-subclass name="application.model.Test" table="t_test" dynamic-update="false" dynamic-insert="false">  <key column="testrange_id"/>  <property node="num" name="num" type="int" update="true" insert="true" access="property" not-null="false" unique="false">  <column name="num"/>  </property>  <property node="val" name="val" type="string" update="true" insert="true" access="property" not-null="false" unique="false">  <column name="val"/>  </property>  </joined-subclass>  </class>  </hibernate-mapping>  一共3个持久化对象模型,TestRange是父类,包含id和name属性,Test和TestGroup是子类,TestGroup中有一个关系为many-to-many的Set,元素为TestRange。  目前set的outer-join=auto,many-to-many的outer-join=auto  看下面测试用例:  public class TestManagerTester extends TestCase {  private TestManager _mgr;  protected void setUp() throws Exception {  super.setUp();  _mgr=(TestManager)BeanFactoryWrapper.getBean(TestManager.class.getName());  }  protected void tearDown() throws Exception {  super.tearDown();  }  public void testManager() {  assertNotNull(_mgr);  List list=_mgr.getTestRanges();  if(list.isEmpty()){  Test test=new Test();  test.setName("abc");  test.setNum(5);  Test test2=new Test();  test2.setNum(6);  TestGroup group=new TestGroup();  group.setName("name");  group.getTestSet().add(test);  group.getTestSet().add(test2);  _mgr.saveTestRange(group);  list=_mgr.getTestRanges();  }  assertNotNull(list);  assertTrue(list.size()>=1);  Iterator iter=list.iterator();  while (iter.hasNext()){  Object obj=iter.next();  // assertTrue(obj instanceof TestGroup);  if(obj instanceof TestGroup){  Set set=((TestGroup) obj).getTestSet();  if(!set.isEmpty()){  Iterator iter2=set.iterator();  while(iter2.hasNext()){  Object obj2=iter2.next();  System.out.println("element value is "+obj2);  System.out.println("in set element class is "+obj2.getClass());  //assertTrue(obj2 instanceof Test);  }  }  }  }  }  }  group的testSet中有2个元素test和test2,test2.name=null,test.name="abc",测试用例运行结果是:  element value is application.model.Test@106df95[id=6,name=<null>,num=6,val=<null>]  in set element class is class application.model.TestRange$$EnhancerByCGLIB$$3119c08f  element value is application.model.Test@176086d[id=5,name=abc,num=5,val=<null>]  in set element class is class application.model.Test  也就是说,对于name为空的集合元素的class有问题,不是正常的Test类,而是CGLIB生成的一个什么类(toString显示的却是正常 的),通过其他测试用例发现,对于set和many-to-many的outer-join均为auto的时候,many-to-many的class为 父类,只要在集合元素中有一个(或以上) 的父类属性值为空,而实际类型为子类的时候,得到的元素的class都有问题。  对hbm文件进行修改,方法如下:  1 把many-to-many的outer-join改为false,结果同上  2 把many-to-many的outer-join改为true,其余不变,测试用例运行结果是:  element value is application.model.Test@16f5261[id=6,name=<null>,num=6,val=<null>]  in set element class is class application.model.Test  element value is application.model.Test@176086d[id=5,name=abc,num=5,val=<null>]  in set element class is class application.model.Test  也就是说结果符合我们的实际需要。  3 many-to-many的outer-join=auto, set的outer-join=true,结果  element value is application.model.Test@1e1ec86[id=6,name=<null>,num=6,val=<null>]  in set element class is class application.model.TestRange$$EnhancerByCGLIB$$b004439a  element value is application.model.Test@15a94f[id=5,name=abc,num=5,val=<null>]  in set element class is class application.model.TestRange$$EnhancerByCGLIB$$b004439a  嘿嘿都错了。  4 many-to-many的outer-join=true, set的outer-join=true 结果  element value is application.model.Test@1304043[id=6,name=<null>,num=6,val=<null>]  in set element class is class application.model.Test  element value is application.model.Test@15a94f[id=5,name=abc,num=5,val=<null>]  in set element class is class application.model.Test  都对的  5 many-to-many的outer-join=true, set的outer-join=false 结果  element value is application.model.Test@16f5261[id=6,name=<null>,num=6,val=<null>]  in set element class is class application.model.Test  element value is application.model.Test@176086d[id=5,name=abc,num=5,val=<null>]  in set element class is class application.model.Test  6 many-to-many的outer-join=auto, set的outer-join=false 结果  element value is application.model.Test@106df95[id=6,name=<null>,num=6,val=<null>]  in set element class is class application.model.TestRange$$EnhancerByCGLIB$$13cc6038  element value is application.model.Test@176086d[id=5,name=abc,num=5,val=<null>]  in set element class is class application.model.Test  test.name=null时出错。  列了这么多现象,等有空时再看源码找问题的根源。  目前我避免问题采取的策略就是尽量不用outer-join=auto选项。


阅读全文(2925) | 回复(0) | 编辑 | 精华
 



发表评论:
昵称:
密码:
主页:
标题:
验证码:  (不区分大小写,请仔细填写,输错需重写评论内容!)



站点首页 | 联系我们 | 博客注册 | 博客登陆

Sponsored By W3CHINA
W3CHINA Blog 0.8 Processed in 0.779 second(s), page refreshed 144807836 times.
《全国人大常委会关于维护互联网安全的决定》  《计算机信息网络国际联网安全保护管理办法》
苏ICP备05006046号