`

Hibernate在配置 one-to-many时应该注意的事项

阅读更多

其实配置one-to-many的映射很简单,就是在one所代表的这个类中添加一个集合对象,一般用set,来保存对应的many所代表的那个类的对象,比如,一个person对应多个order,(一个人对应多个订单),那么在person类中添加private Set<Order> order ;这个属性,然后提供get,set方法

然后在Person.hbm.xml中配置:

<set name="order" inverse="true" cascade="all">
   <key column="userid" />
   <one-to-many class="Order" />
</set>

 这样,一个单向的一对多关系就配置完成了,在主程序中新建order对象,保存进set中,再把person.setOrder(set),然后保存order对象,保存person对象就行了。但是这样配置有很大的问题,在数据库中的处理是先是往order表和person表中插入数据,但是order表的外键列插入的是null,然后执行更新语句,更新order表的外键列,把它设置成对应的personid

如下控制台输出的信息:(里面有张表是userinfo而不是personinfo)

Hibernate: insert into USERINFO (username, password, userid) values (?, ?, ?)
Hibernate: insert into ORDERINFO (product, oid) values (?, ?)
Hibernate: insert into ORDERINFO (product, oid) values (?, ?)
Hibernate: insert into ORDERINFO (product, oid) values (?, ?)
Hibernate: update ORDERINFO set USERID=? where oid=?
Hibernate: update ORDERINFO set USERID=? where oid=?
Hibernate: update ORDERINFO set USERID=? where oid=?

这样操作的话性能就很不好了,

如果设置双向一对多关联,那么就很好了,就是在order类中加一个属性private Person person,然后提供get,set方法,然后在Order.hbm.xml中配置

<many-to-one name="person" class="Person" column="personid" />,然后在主程序中,order.set(person),要设置值(控制关联关系),其他的和上面的一样,这样

控制台输出信息如下:

Hibernate: insert into USERINFO (username, password, userid) values (?, ?, ?)
Hibernate: insert into ORDERINFO (product, USERID, oid) values (?, ?, ?)
Hibernate: insert into ORDERINFO (product, USERID, oid) values (?, ?, ?)
Hibernate: insert into ORDERINFO (product, USERID, oid) values (?, ?, ?)

就只有4条插入语句在操作数据库了。

 

关于双向一对多的操作注意一下几点:(引用自李刚的JAVAEEssh整合开发那本书)

1.先持久化one的对象

2.先设置one和many的关联关系,在保存many对象,否则还是会出现先插入,然后再更新的重复操作数据库的现象

3.不要通过one的那一端来控制关联关系,可以设置set的inverse=“true”来控制,或者在主程序中不通过设置set来关联两个类

(inverse的意思是反转,用来设置关系哪一方是拥有者owner,由他来维护这个关系。

作用是在一对多双向关联关系中使一方放弃维护到对方的关系(抽象)。其实就是减少重复执行多余的SQL语句 )

inverse="false" 是默认情况,此时没有反转,则 Set/Collection 关系由包含它的“一”这一方来维;

 

inverse="true" 时,表示 Set/Collection 关系由另一方来维护,由不包含这个关系的一方来维护这个关系,所以才称为“反转”了

 

实例分析:

以Student(学生)和Class(班级)为例,它们之间的关系为一对多的关系,即一个学生只能属于一个班级,一个班级可以包含多个学生。

Class班级:
Class Class{
  private int id;
  private String name;
  private Set students = new HashSet();
  //省略getter()和setter()方法
}
 Student学生:
Class Student{
  private int id;
  private String name;
  private Class class;
  //省略getter()和setter()方法
}
 Class类的映射文件:
<class name="Class" table="CLASS">
   <id name="id" type="int" column="ID">
     <generator class="native" />  
   </id>
   <property name="name" type="string" column="NAME" />
   <set name="students" table="STUDENT" cascade="save-update" inverse="false">
     <key column="CLASS_ID" />
     <one-to-many class="Student" />
   </set>
</class>
Student类的映射文件:
<class name="Student" table="STUDENT">
   <id name="id" type="int" column="ID">
      <generator class="native" />  
   </id>
   <property name="name" type="string" column="NAME" />
   <many-to-one name="class" column="CLASS_ID" class="Class" cascade="save-update" /> 
</class>
 
STUDENT表中存在一个名为CLASS_ID的字段,它和CLASS表中的ID字段是主外键关系。那个inverse属性就是用来规定是由谁(Student或Class)来维护这个主外键关系的。

inverse的默认值为false。 在处理逻辑代码中,如下:
Class c1 = new Class();
c1.setName("一班");
Student s1 = new Student();
Student s2 = new Student();
s1.setName("Jason");
s2.setName("Tom");
c1.getStudents().add(s1);
c2.getStudents().add(s2);
s1.setClass(c1);
s2.setClass(c1);   //注释1
session.save(c1);

上面的代码会使Hibernate执行五条SQL语句,其中前三条是insert插入语句,后两条是update更新语句。插入就不用说了,那么为什么还要有更新语句呢?这是因为Class类映射文件的<set>元素中指定了inverse="false",这就告之Hibernate:STUDENT表与CLASS表的主外键关系是由Class类来维护的。当执行save后,执行了三条insert语句,这三条语句中的后两条是插入到STUDENT表的,它们的CLASS_ID字段是通过s1.getClass().getID()取出的,假如我将上面“注释1”处修改为s2.setClass(c2);(c2是另一个Class对象,可能是持久化对象),这样,主外键关系不就乱了吗。为了保证主外键关系,Hibernate在这种情况下会再执行两条update语句来更改STUDENT表中两个新插入记录的CLASS_ID字段,当然,这时CLASS_ID字段的取值是从c1对象中直接取得,而不再是s1.getClass().getID()方式了。
如果我们将Class类映射文件的<set>元素中的inverse属性修改为true,这就是告诉Hibernate:Class类不维护主外键关系了,这个任务就交给了Student类。于是,我们再执行上面的代码,Hibernate就会只执行三条insert语句,而不会执行任何update语句。因为Hibernate会通过Student类的s1.getClass().getID()和s2.getClass().getID()来确定CLASS_ID字段的值。
故,为了节省数据库资源,省却不必要的update语句,我们一般建议在一对多双向关联关系中,将一方的inverse属性设置为true,即将主外键的关系交由多方来维护。
打个比方:在一个公司中,是老板认识所有的员工容易,还是所有员工认识老板容易?
分享到:
评论

相关推荐

    hibernate one-to-many 单/双向关联映射配置心得

    NULL 博文链接:https://yinxiaoyong.iteye.com/blog/426752

    many-to-one 配置详解

    many-to-one 配置详解 讲的很清楚 适合新手 值得下载

    hibernate xml配置和@注解配置关系映射

    针对hibernate关系映射进行了一个总结,包含xml配置形式和@注解配置形式,one-to-many,one-to-noe,many-to-one,many-to-many等单方向的配置和双方都配置的事例

    基于Java的Hibernate MySQL数据持久化示例设计源码

    该示例包含了基于XML和Annotation的Hibernate配置,涵盖了one-to-one、one-to-many、many-to-many映射关系的配置,并提供了独立的测试用例。适合用于学习和实践Java和Hibernate技术,以及开发基于MySQL的数据持久化...

    hibernate one_to_many

    讲解hibernate的ont_to_many关系配置,希望对你有点用处,谢谢

    Hibernate one to many(many to one) 配置

    NULL 博文链接:https://fqh1987.iteye.com/blog/791845

    hibernate关系映射配置.rar

    &lt;many-to-one name="group" column="groupid" cascade="all"/&gt; --&gt; &lt;many-to-one name="group" column="groupid"/&gt; &lt;/hibernate-mapping&gt; &lt;hibernate-mapping&gt; &lt;class name="com.bjsxt.hibernate.Group...

    hibernate-shards.jar

    non-free programs enables many more people to use the whole GNU operating system, as well as its variant, the GNU/Linux operating system. Although the Lesser General Public License is Less ...

    hibernate 体系结构与配置 参考文档(html)

    多对一(many-to-one) 5.1.11. 一对一 5.1.12. 自然ID(natural-id) 5.1.13. 组件(component), 动态组件(dynamic-component) 5.1.14. properties 5.1.15. 子类(subclass) 5.1.16. 连接的子类(joined-subclass...

    HibernateAPI中文版.chm

    5.1.10. 多对一(many-to-one) 5.1.11. 一对一 5.1.12. 自然ID(natural-id) 5.1.13. 组件(component), 动态组件(dynamic-component) 5.1.14. properties 5.1.15. 子类(subclass) 5.1.16. 连接的子类(joined-...

    hibernate3.2中文文档(chm格式)

    5.1.10. 多对一(many-to-one) 5.1.11. 一对一 5.1.12. 自然ID(natural-id) 5.1.13. 组件(component), 动态组件(dynamic-component) 5.1.14. properties 5.1.15. 子类(subclass) 5.1.16. 连接的子类(joined-...

    Hibernate+中文文档

    5.1.10. 多对一(many-to-one) 5.1.11. 一对一 5.1.12. 自然ID(natural-id) 5.1.13. 组件(component), 动态组件(dynamic-component) 5.1.14. properties 5.1.15. 子类(subclass) 5.1.16. 连接的子类(joined-...

    Hibernate_3.2.0_符合Java习惯的关系数据库持久化

    5.1.10. 多对一(many-to-one) 5.1.11. 一对一 5.1.12. 自然ID(natural-id) 5.1.13. 组件(component), 动态组件(dynamic-component) 5.1.14. properties 5.1.15. 子类(subclass) 5.1.16. 连接的子类(joined-...

    最全Hibernate 参考文档

    5.1.10. 多对一(many-to-one) 5.1.11. 一对一 5.1.12. 组件(component), 动态组件(dynamic-component) 5.1.13. properties 5.1.14. 子类(subclass) 5.1.15. 连接的子类(joined-subclass) 5.1.16. 联合子类(union-...

    Hibernate中文详细学习文档

    5.1.10. 多对一(many-to-one) 5.1.11. 一对一 5.1.12. 自然ID(natural-id) 5.1.13. 组件(component), 动态组件(dynamic-component) 5.1.14. properties 5.1.15. 子类(subclass) 5.1.16. 连接的子类(joined-...

    jsonplugin, 对 struts2.1.X版本jsonplugin-0.34.jar 的修改

    第一次上传,要5分,是物有所值,处理了jsonplugin 的no session的问题,并且添加了,新的注释,例如 ...2.对one-ton-many ,one-to-one ,值设为null(被设置为延迟加载的时候) 3.不需要配置底层实体,在当前action配置就可以

    Hibernate 中文 html 帮助文档

    5.1.10. 多对一(many-to-one) 5.1.11. 一对一 5.1.12. 自然ID(natural-id) 5.1.13. 组件(component), 动态组件(dynamic-component) 5.1.14. properties 5.1.15. 子类(subclass) 5.1.16. 连接的子类(joined-...

    hibernate annotation 中文文档

    多对一(Many-to-one) 2.2.5.3. 集合类型 2.2.5.4. 用cascading实现传播性持久化(Transitive persistence) 2.2.5.5. 关联关系获取 2.2.6. 映射复合主键与外键 2.2.7. 映射二级表(secondary tables) 2.3. 映射查询 ...

    Hibernate教程

    6.1.10. 多对一(many-to-one) 6.1.11. 一对一 6.1.12. 组件(component), 动态组件(dynamic-component) 6.1.13. properties 6.1.14. 子类(subclass) 6.1.15. 连接的子类(joined-subclass) 6.1.16. 联合子类...

    精通Hibernate之映射继承关系(六)

    Company与Employee类之间为一对多多态关联关系,如果继承关系树的根类对应一个表,或者每个类对应一个表,那么就能映射Company类的employees集合。...many-to-onename="a"class="ClassA"column="A_ID"cascade="s

Global site tag (gtag.js) - Google Analytics