zoukankan      html  css  js  c++  java
  • 在测试Hibernate的一对多双向关联映射时

    在测试Hibernate的一对多双向关联映射时,碰到很有趣的问题,跟inverse属性直接相关。

    1、People.hbm.xml

    <hibernate-mapping default-lazy="false">
    <class name="com.persistent.People" table="people">
    <id name="id" column="peopleId" unsaved-value="0">
    <generator class="increment">
    </generator>
    </id>
    <property name="name" column="name"></property>
    <set name="addresses" cascade="save-update">
    <key column="peopleId" not-null="true" />
    <one-to-many class="com.persistent.Address"/>
    </set>
    </class>
    </hibernate-mapping>

    2、Address.hbm.xml

    <hibernate-mapping>
    <class name="com.persistent.Address" table="address">
    <id name="id" column="addressId" unsaved-value="0">
    <generator class="increment">
    </generator>
    </id>
    <many-to-one name="people" column="peopleId" insert="false" update="false"></many-to-one>
    <property name="addressName" column="addressName"></property>
    <property name="codeNumber" column="codeNumber"></property>
    </class>
    </hibernate-mapping>
    3、People.java和Address.java

    public class People ...{
    private long id;
    private String name;
    private Set addresses = new HashSet();
    ...
    }

    public class Address ...{
    private long id;
    private People people;
    private String addressName;
    private String codeNumber;
    ...
    }

    4、数据库结构

    people表:{peopleId,name}

    address表:{addressId,peopleId,addressName,codeNumber}

    5、测试代码

    People people = new People();
    people.setName("linda");
    Address address = new Address();
    address.setAddressName("yunnan");
    address.setCodeNumber("564123");
    address.setPeople(people);
    people.getAddresses().add(address);
    Session session = HibernateSessionFactory.getSession();
    session.beginTransaction();
    session.save(people);
    session.getTransaction().commit();

    6、运行结果

      上面测试代码运行起来正确:

    Hibernate: select max(peopleId) from people
    Hibernate: select max(addressId) from address
    Hibernate: insert into people (name, peopleId) values (?, ?)
    Hibernate: insert into address (addressName, codeNumber, peopleId, addressId) values (?, ?, ?, ?)
    Hibernate: update address set peopleId=? where addressId=?

      如果将People.hbm.xml映射改写一下:

    <set name="addresses" cascade="save-update" inverse="true">
    <key column="peopleId" not-null="true" />
    <one-to-many class="com.persistent.Address"/>
    </set>

      不同之处在于添加了inverse="true",结果:

    Hibernate: select max(peopleId) from people
    Hibernate: select max(addressId) from address
    Hibernate: insert into people (name, peopleId) values (?, ?)
    Hibernate: insert into address (addressName, codeNumber, addressId) values (?, ?, ?)

      可以看到,peopleId并没有写入到关联的address当中,数据库address表中相应记录的peopleId字段为空。

    7、分析

      在Hibernate中,术语inverse是反转的意思,在关联关系中,inverse="false"为主控方,由主控方负责维护对象的关联关系。所以上面的映射文件改动之后,address为主控方,people为被控方,但是测试代码只进行了一个保存操作session.save(people),这是针对people的,因此无法正确级联保存address。而原来的映射文件中(虽然没有明确指明,Hibernate默认inverse="false"),people为主控方,因此保存people时它会保证关联的address的正确保存。

      也就是说,Hibernate仅仅按照主控方对象的状态的变化来同步更新数据库。按照原来的映射文件,people.getAddresses().add(address),即主控方对象的状态发生了改变,因此数据库会跟着对象状态的变化来同步更新数据库;而address.setPeople(people),即被控方对象的状态发生了改变,它是不能触发对象和数据库的同步更新的。

  • 相关阅读:
    vim删除行尾的^M
    apt-get方式安装lnmp环境
    oracle vm virtualbox右ctrl切换显示模式
    chrome(谷歌浏览器)老是提示此文件可能损害计算机
    tmux允许鼠标滚动
    tmux不自动加载配置文件.tmux.conf
    elfutils cc1: all warnings being treated as errors
    Can't locate find.pl in @INC (@INC contains: /etc/perl xxxx) at perlpath.pl line 7.
    help2man: can't get `--help' info from automake-1.15 Try `--no-discard-stderr' if option outputs to stderr Makefile:3687: recipe for target 'doc/automake-1.15.1' failed
    Unescaped left brace in regex is illegal here in regex; marked by <-- HERE in m/${ <-- HERE ([^ =:+{}]+)}/ at xxxx/usr/bin/automake line 3939.
  • 原文地址:https://www.cnblogs.com/java20130726/p/3218442.html
Copyright © 2011-2022 走看看