理解hibernate的inverse! many-to-many

Inverse hibernate 双向关系中的基本概念,当然对于多数实体,我们并不需要双向关联,更多的可能会选择单向关联,况且我们大多数人一般采用一对多关系, 而一对多双向关联的另一端:多对一的 inverse 属性是不存在,其实它默认就是 inverse=false. 从而防止了在一对多端胡乱设置 inverse 也不至于出错。但是 inverse 设置不当确实会带来很大的性能影响,这点是我们必须关注的。

这篇文章已经详细分析了 inverse 设置不当带来的影响:

http://www.hibernate.org/155.html    (这个链接已经无效了,直接看下面的也可以使你能够较好的理解 hibernate inverse

看了这篇文章,还是很有必要再写下一些总结的:

1 inverse 中提及的 side 其实是指一个类或者表的概念,双向关联其实是指双方都可以取得对方的应用。

2 维护关系这个名词还是稍显模糊或者晦涩。我们一般说 A 类或者 A 表(这里的表的是指多对多的连接表)有责任维护关系,其实这里的意思是说,我在应用在更新, 创建,删除(读就不用说了,双向引用正是为了方便读而出现) A 类或者 A 表时,此时创建的 SQL 语句必须有责任保证关系的正确修改。

3 inverse=false side side 其实是指 inverse false 所位于的 class 元素)端有责任维护关系,而 inverse true 端无须维护这些关系。

4 我们说 inverse 设立不当会导致性能低下,其实是说 inverse 设立不当,会产生多余重复的 SQL 语句甚至致使 JDBC exception throw 。这是我们在建立实体类关系时必须需要关注的地方。一般来说, inverse true 是推荐使用,双向关联中双方都设置 inverse false 的话,必会导致双方都重复更新同一个关系。但是如果双方都设立 inverse true 的话,双方都不维护关系的更新,这也是 不行的,好在一对多中的一端 :many-to-one 默认是 inverse false ,避免了这种错误的产生。但是对多对就没有这个默认设置了,所以很 多人经常在多对多的两端都使用 inverse true ,结果导致连接表的数据根本没有记录,就是因为他们双分都没有责任维护关系。所以说,双向关联中最 好的设置是一端为 inverse true ,一端为 inverse false 。一般 inverse false 会放在多的一端,那么有人提问 了, many to many 两边都是多的, inverse 到底放在哪儿?其实 hibernate 建立多对多关系也是将他们分离成两个一对多关系,中间连 接一个连接表。所以通用存在一对多的关系,也可以这样说:一对多是多对多的基本组成部分。

下面的多对多的定义大家更会清楚 多对多 一对多 的关系:其中我们注意 <many-to-many></many-to- many> 标签的特点就知道,它是定义了一个多对多关系,而不是 <one-to-many></one-to- many>


 "-//Hibernate/Hibernate Mapping DTD 2.0//EN"
 "http://hibernate.sourceforge.net/hibernate-mapping-2.0.dtd ">
<hibernate-mapping></hibernate-mapping>
 <class table="TestA" name="TestA"></class>  dynamic-update="true" dynamic-insert="true" >

  <id name="id" column="id" type="int" unsaved-value="any"></id>
   <generator class="assigned"></generator>
   
  

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

  
   <key column="testA"></key>
   <many-to-many class="TestB" column="testB"></many-to-many>
  


 
 <class table="TestB" name="TestB"></class>  dynamic-update="true" dynamic-insert="true" >

  <id name="id" column="id" type="int" unsaved-value="any"></id>
   <generator class="assigned"></generator>
   
  

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

  
   <key column="testB"></key>
   <many-to-many class="TestA" column="testA"></many-to-many>
  


 


在对多对中,因为一端维护关系另一端不维护关系的原因,我们必须注意避免在应用中用不维护关系的类建立关系,因为这样建立的关系是不会在数据库中存储的。基于上面的映射文件代码给出一个例子:

package org.hibernate.auction;
import java.util.*;

/**
 * @author Administrator
 *
 * To change the template for this generated type comment go to
 * Window>Preferences>Java>Code Generation>Code and Comments
 */
public class TestA {
 int id;
 String name;
 Set testBs=new HashSet();
 public TestA(){
 
 }
 public TestA(int id){
  setId(id);
 }
 public int getId(){
  return id;
 }
 public void setId(int id){
  this.id=id;
 }
 public String getName(){
  return name;
 }
 public void setName(String name){
  this.name=name;
 }
 public Set getTestBs(){
  return testBs;
 }
 public void setTestBs(Set s){
  testBs=s;
 }
 public void addTestB(TestB tb){
  testBs.add(tb);
 }

 public static void main(String[] args) {
 }
}


public class TestB {

 
 int id;
 String name;
 Set testAs=new HashSet();
 public TestB(){
 
 }
 public TestB(int id){
  setId(id);
 }
 public int getId(){
  return id;
 }
 public void setId(int id){
  this.id=id;
 }
 public String getName(){
  return name;
 }
 public void setName(String name){
  this.name=name;
 }
 public Set getTestAs(){
  return testAs;
 }
 public void setTestAs(Set s){
  testAs=s;
 }
 public void addTestA(TestA ta){
  testAs.add(ta);
 }
 public static void main(String[] args) {
 }
}

测试代码:

public void doTest() throws Exception{
  TestA a1=new TestA(1);
  TestA a2=new TestA(2);
  TestA a3=new TestA(3);
  TestB b1=new TestB(1);
  TestB b2=new TestB(2);
  TestB b3=new TestB(3);
  a1.addTestB(b1);
  a1.addTestB(b2);
  a1.addTestB(b3);
  b2.addTestA(a1);
  b2.addTestA(a2);
 
  Session s = factory.openSession();
 
  s = factory.openSession();
 
 
  Session session = factory.openSession();
  session.save(a1);
  session.flush();
  session.close();

 }

测试后连接表的数据为:

testa              testb

1                  1

1                  2

1                  3

根据 inverse 规则,对这些代码: b2.addTestA(a1);  b2.addTestA(a2); 建立的关系,数据库并没有存储下来,因为 TestB 没有责任维护这些关系,所以产生的 sql 语句自然不会有针对 Testa_testB 表的操作了。假设应 用中真的需要这些方法,那么我们可以修改 TestB 的方法,让他们注意在维护端类中执行相应的操作以使得关系能够在数据库中保存下来,更改 TestB 下:

/*
 * Created on 2004-7-25
 *
 * To change the template for this generated file go to
 * Window>Preferences>Java>Code Generation>Code and Comments
 */
package org.hibernate.auction;
import java.util.*;

/**
 * @author Administrator
 *
 * To change the template for this generated type comment go to
 * Window>Preferences>Java>Code Generation>Code and Comments
 */
public class TestB {

 
 int id;
 String name;
 Set testAs=new HashSet();
 public TestB(){
 
 }
 public TestB(int id){
  setId(id);
 }
 public int getId(){
  return id;
 }
 public void setId(int id){
  this.id=id;
 }
 public String getName(){
  return name;
 }
 public void setName(String name){
  this.name=name;
 }
 public Set getTestAs(){
  return testAs;
 }
 public void setTestAs(Set s){
  testAs=s;
 }
 public void addTestA(TestA ta){
  testAs.add(ta);
  ta.addTestB(this);
 }
 public static void main(String[] args) {
 }
}
那么测试执行后连接表的数据为:

testa          testb

1               2

1               3

1                1

2                 2

测试通过。

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
提供的源码资源涵盖了安卓应用、小程序、Python应用和Java应用等多个领域,每个领域都包含了丰富的实例和项目。这些源码都是基于各自平台的最新技术和标准编写,确保了在对应环境下能够无缝运行。同时,源码中配备了详细的注释和文档,帮助用户快速理解代码结构和实现逻辑。 适用人群: 这些源码资源特别适合大学生群体。无论你是计算机相关专业的学生,还是对其他领域编程感兴趣的学生,这些资源都能为你提供宝贵的学习和实践机会。通过学习和运行这些源码,你可以掌握各平台开发的基础知识,提升编程能力和项目实战经验。 使用场景及目标: 在学习阶段,你可以利用这些源码资源进行课程实践、课外项目或毕业设计。通过分析和运行源码,你将深入了解各平台开发的技术细节和最佳实践,逐步培养起自己的项目开发和问题解决能力。此外,在求职或创业过程中,具备跨平台开发能力的大学生将更具竞争力。 其他说明: 为了确保源码资源的可运行性和易用性,特别注意了以下几点:首先,每份源码都提供了详细的运行环境和依赖说明,确保用户能够轻松搭建起开发环境;其次,源码中的注释和文档都非常完善,方便用户快速上手和理解代码;最后,我会定期更新这些源码资源,以适应各平台技术的最新发展和市场需求。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值