3-hibernate 多对多关联的实现

Hibernate多对多的测试纪录- -
                                     
多对多映射试验纪录 :

一、Jeff类:
public class Jeff {
 private int id;
 private int version;
 private String name;
 private Set heyhey = new HashSet();
 //省略Getter setter
}
二、Heyhey类
public class Heyhey {
 private int id;
 private int version;
 private String name;
 private Set heyhey = new HashSet();
 //省略Getter setter
}
三、JEFF表:
id int not-null
version int not-null
name varchar null
四、HEYHEY表:
id int not-null
version int not-null
name varchar null
五,JEFF_HEYHEY表,即中间表:
JeffID int not-null
HeyheyID int not-null
六、HBM文件是在测试中改动的。原来的代码:
Jeff.hbm.xml文件:
<hibernate-mapping
>
    <class
        name="com.botwave.cncd.business.entity.Jeff"
        table="JEFF"
        lazy="true"
        optimistic-lock="version"
    >

        <id
            name="id"
            column="id"
            type="int"
            length="8"
            unsaved-value="0"
        >
            <generator class="identity">
            </generator>
        </id>

        <version
            name="version"
            column="version"
            type="java.lang.Integer"
        />

        <set
            name="heyhey"
            table="JEFF_HEYHEY"
            lazy="true"
            cascade="save-update"
        >

            <key
                column="jeffID"
            >
            </key>

            <many-to-many
                class="com.botwave.cncd.business.entity.Heyhey"
                column="heyheyID"
                outer-join="auto"
             />

        </set>
        <property
            name="name"
            type="java.lang.String"
            update="true"
            insert="true"
            column="name"
            length="20"
        />

   </class>

</hibernate-mapping>

Heyhey.hbm.xml文件:

<hibernate-mapping
>
    <class
        name="com.botwave.cncd.business.entity.Heyhey"
        table="HEYHEY"
        lazy="true"
        optimistic-lock="version"
    >

        <id
            name="id"
            column="id"
            type="int"
            length="8"
            unsaved-value="0"
        >
            <generator class="identity">
            </generator>
        </id>

        <version
            name="version"
            column="version"
            type="java.lang.Integer"
        />

        <set
            name="jeff"
            table="JEFF_HEYHEY"
            lazy="true"
            inverse = "true"
            cascade="save-update"
        >

            <key
                column="heyheyID"
            >
            </key>

            <many-to-many
                class="com.botwave.cncd.business.entity.Jeff"
                column="jeffID"
                outer-join="auto"
             />
        </set>
        <property
            name="name"
            type="java.lang.String"
            update="true"
            insert="true"
            column="name"
            length="20"
        />
            </class>

</hibernate-mapping>
-----------------------------------------
第一种情况:在Heyhey.hbm.xml文件的Set元素中设置inverse元素为true,另一个为默认,即False
测试代码如下:
JeffService js = new JeffServiceImpl();
Heyhey hey1 = new Heyhey();
Jeff jeff1 = (Jeff)js.findObjectById(1);
hey1.setName("unknow");
jeff1.getHeyhey().add(hey1);
sess.saveOrUpdate(jeff1);
这是更新一个已有的实体的代码,测试结果如下:
Hibernate: select jeff0_.id as id0_, jeff0_.version as version0_, jeff0_.name as name0_ from JEFF jeff0_ where jeff0_.id=?
Hibernate: select heyhey0_.heyheyID as heyheyID__, heyhey0_.jeffID as jeffID__ from JEFF_HEYHEY heyhey0_ where heyhey0_.jeffID=?
Hibernate: insert into HEYHEY (version, name) values (?, ?)
Hibernate: update JEFF set version=?, name=? where id=? and version=?
Hibernate: insert into JEFF_HEYHEY (jeffID, heyheyID) values (?, ?)
分析:第一句查询是js.findObjectById(1)生成的,第二句查询是jeff1.getHeyhey()生成的,查询了中间表,第三、四、五句是sess.saveOrUpdate(jeff1);生成的。
当Session发现Jeff1需要更新的时候,它的heyhey元素发生了变化,于家先持久化hey1,所以有了第三句,然后更新自已的表(在这里这句是不起作用的,因为更新不到本表的数据),最后才在中间表插入一条数据。

第二种情况,配置文件不变,代码如下:
Transaction tx = sess.beginTransaction();
JeffService js = new JeffServiceImpl();
HeyheyService hs = new HeyheyServiceImpl();
Heyhey hey1 = (Heyhey)hs.findObjectById(7);
Jeff jeff1 = (Jeff)js.findObjectById(1);
hey1.setName("haha");

jeff1.getHeyhey().add(hey1);
System.out.println("before update");
sess.saveOrUpdate(jeff1);

tx.commit();
测试结果如下:
Hibernate: select heyhey0_.id as id0_, heyhey0_.version as version0_, heyhey0_.name as name0_ from HEYHEY heyhey0_ where heyhey0_.id=?
Hibernate: select jeff0_.id as id0_, jeff0_.version as version0_, jeff0_.name as name0_ from JEFF jeff0_ where jeff0_.id=?
Hibernate: select heyhey0_.heyheyID as heyheyID__, heyhey0_.jeffID as jeffID__ from JEFF_HEYHEY heyhey0_ where heyhey0_.jeffID=?
Hibernate: update JEFF set version=?, name=? where id=? and version=?
Hibernate: insert into JEFF_HEYHEY (jeffID, heyheyID) values (?, ?)
分析:第一二句是查找两个已存在的实体用的,第三句是GetHeyhey()时生成的,第四五句是更新实体是生成的。第四句同样是不起作用的。


第三种情况:在Jeff.hbm.xml文件的Set元素中设置inverse元素为true,另一个为默认,即False
测试代码同第一种
测试结果如下:
Hibernate: select jeff0_.id as id0_, jeff0_.version as version0_, jeff0_.name as name0_ from JEFF jeff0_ where jeff0_.id=?
Hibernate: select heyhey0_.heyheyID as heyheyID__, heyhey0_.jeffID as jeffID__ from JEFF_HEYHEY heyhey0_ where heyhey0_.jeffID=?
Hibernate: insert into HEYHEY (version, name) values (?, ?)
Hibernate: update JEFF set version=?, name=? where id=? and version=?
分析:这一次,Hibernate没有把数据加入中间表。就是因为Inverse元素的位置调转了。待研究。

第四种情况,配置文件同上,测试代码同第二种
测试结果:
Hibernate: select heyhey0_.id as id0_, heyhey0_.version as version0_, heyhey0_.name as name0_ from HEYHEY heyhey0_ where heyhey0_.id=?
Hibernate: select jeff0_.id as id0_, jeff0_.version as version0_, jeff0_.name as name0_ from JEFF jeff0_ where jeff0_.id=?
Hibernate: select heyhey0_.heyheyID as heyheyID__, heyhey0_.jeffID as jeffID__ from JEFF_HEYHEY heyhey0_ where heyhey0_.jeffID=?
Hibernate: update HEYHEY set version=?, name=? where id=? and version=?
Hibernate: update JEFF set version=?, name=? where id=? and version=?
分析:这一次,两个表都分别更新了,但是却没有数据插入中间表。是Inverse元素作的怪。先注意这种情况。慢慢研究。

第五种情况,配置文件同上,代码为:
Transaction tx = sess.beginTransaction();
JeffService js = new JeffServiceImpl();
HeyheyService hs = new HeyheyServiceImpl();
Heyhey hey1 = new Heyhey();
Jeff jeff1 = new Jeff();
hey1.setName("ahah");
jeff1.setName("haefe1");

jeff1.getHeyhey().add(hey1);
System.out.println("before update");
sess.saveOrUpdate(jeff1);

tx.commit();
意为新建两个对象,然后建立关系。结果:
Hibernate: insert into JEFF (version, name) values (?, ?)
Hibernate: insert into HEYHEY (version, name) values (?, ?)
还是没有插入到中间表去。

第六种情况,配置调换回来。代码同上。结果:
Hibernate: insert into JEFF (version, name) values (?, ?)
Hibernate: insert into HEYHEY (version, name) values (?, ?)
Hibernate: insert into JEFF_HEYHEY (jeffID, heyheyID) values (?, ?)
这次就看到插入中间表了。

第七种情况,想在一个表取出一些纪录,同时新建另一个表的一个实体,把前者的纪录集和后者关联保存。配置同第一种,代码如下:
Transaction tx = sess.beginTransaction();
   JeffService js = new JeffServiceImpl();
   HeyheyService hs = new HeyheyServiceImpl();
            Integer[] as = new Integer[3];
            as[0] = new Integer(1);
            as[1] = new Integer(2);
            as[2] = new Integer(3);
            List heyheys = hs.findObjectsByIds(as);//找到已存在的几条纪录。
   Jeff jeff1 = new Jeff();
   jeff1.setName("你老豆");
   Set set = new HashSet();
            set.add(heyheys);
    
            jeff1.setHeyhey(set);
     System.out.println(jeff1.getHeyhey());
   System.out.println("before update");
   sess.saveOrUpdate(jeff1);
  
   tx.commit();
结果如下:
Hibernate: select this.id as id0_, this.version as version0_, this.name as name0_ from HEYHEY this where this.id in (?, ?, ?)
[[com.botwave.cncd.business.entity.Heyhey@12696c2,
com.botwave.cncd.business.entity.Heyhey@98350a]]  //这里打印出Heyhey()里面有什么。
before update
Hibernate: insert into JEFF (version, name) values (?, ?)
net.sf.hibernate.MappingException: No persister for: java.util.ArrayList//抛出异常,不能持久化List类。

第八种情况,目的同第七种,代码如下:
Transaction tx = sess.beginTransaction();
   JeffService js = new JeffServiceImpl();
   HeyheyService hs = new HeyheyServiceImpl();
            Integer[] as = new Integer[3];
            as[0] = new Integer(1);
            as[1] = new Integer(2);
            as[2] = new Integer(3);
            List heyheys = hs.findObjectsByIds(as);
   Jeff jeff1 = new Jeff();
   jeff1.setName("你老豆");
            for(int i = 0;i < heyheys.size();i ++){
                jeff1.getHeyhey().add(heyheys.get(i));
            }
            System.out.println(jeff1.getHeyhey());
   System.out.println("before update");
   sess.saveOrUpdate(jeff1);
  
   tx.commit();
这次与第七种情况不同的是,在设置Jeff1的Heyheys属性的时候,是先Get再逐个添加。这次的结果是:
Hibernate: select this.id as id0_, this.version as version0_, this.name as name0_ from HEYHEY this where this.id in (?, ?, ?)
[com.botwave.cncd.business.entity.Heyhey@c24193,
com.botwave.cncd.business.entity.Heyhey@739f3f]
before update
Hibernate: insert into JEFF (version, name) values (?, ?)
Hibernate: insert into JEFF_HEYHEY (jeffID, heyheyID) values (?, ?)
成功插入数据及中间表。

猜想:多对多的关取能否在VO时期关联好,然后复制到PO再保存?

第九种情况,正是实现以上猜想的。配置不变,代码如下:
Transaction tx = sess.beginTransaction();
   JeffService js = new JeffServiceImpl();
   HeyheyService hs = new HeyheyServiceImpl();
            Integer[] as = new Integer[3];
            as[0] = new Integer(1);
            as[1] = new Integer(2);
            as[2] = new Integer(3);
            List heyheys = hs.findObjectsByIds(as);
            JeffForm jf = new JeffForm();
   Jeff jeff1 = new Jeff();
   jf.setName("你vc");
            for(int i = 0;i < heyheys.size();i ++){
                jf.getHeyhey().add(heyheys.get(i));
            }
            System.out.println(jf.getHeyhey());
            CommonUtil.copyProperties(jeff1,jf);
   System.out.println("before update");
   sess.saveOrUpdate(jeff1);
  
   tx.commit();
分析:CommonUtil.copyProperties(jeff1,jf);是用了BeanUtils组件的CopyProperties的方法。JeffForm的结构和Jeff的结构完全一样。
结果:Hibernate: select this.id as id0_, this.version as version0_, this.name as name0_ from HEYHEY this where this.id in (?, ?, ?)
[com.botwave.cncd.business.entity.Heyhey@c24193,
com.botwave.cncd.business.entity.Heyhey@739f3f]
before update
Hibernate: insert into JEFF (version, name) values (?, ?)
Hibernate: insert into JEFF_HEYHEY (jeffID, heyheyID) values (?, ?)
同样成功!!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值