现在的位置: 首页 > 综合 > 正文

outer-join的简单学习

2013年09月22日 ⁄ 综合 ⁄ 共 3946字 ⁄ 字号 评论关闭

在hibernate的对象关联中慎用outer-join属性值(many-to-many的集元素属性错误备忘) 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文件:

 

 

一共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=,num=6,val=] 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=] 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=,num=6,val=] in set element class is class application.model.Test element value is application.model.Test@176086d[id=5,name=abc,num=5,val=] 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=,num=6,val=] 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=] 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=,num=6,val=] in set element class is class application.model.Test element value is application.model.Test@15a94f[id=5,name=abc,num=5,val=] 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=,num=6,val=] in set element class is class application.model.Test element value is application.model.Test@176086d[id=5,name=abc,num=5,val=] 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=,num=6,val=] 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=] in set element class is class application.model.Test test.name=null时出错。 列了这么多现象,等有空时再看源码找问题的根源。

抱歉!评论已关闭.