inverse java_Hibernate中的inverse的用法

总结:直观来说所有双向关联须有有一段设置为inverse。在一对多的关联中它必须代表多(many)的那端。而在多对多(many-to-many)关联中,可以选取任意一端,因为两端之间并没有差别。

以下为转贴:

通过Hibernate Inverse的设置来决定是由谁来维护表和表之间的关系。最近有朋友问我Hibernate关于多对多关于删除中间表数据的问题,关键是Inverse的设置,下面引用网友的一篇文章。

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

关于inverse和cascade的区别

cascade:设置级联

sava-update:级联保存、更新

delete:级联删除

none:不级联,默认值

all:级联保存、更新、删除

inverse:在映射一对多关系时,一般将该属性设置为true,表示表间的关联关系由一方设置,减少update语句,提高性能

这篇文章已经详细分析了Hibernate Inverse设置不当带来的影响:http://www.Hibernate.org/155.html,看了这篇文章,还是很有必要再写下一些总结的:

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

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

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

4)我们说Hibernate 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建立多对多关系也是将他们分离成两个一对多关系,中间连接一 个连接表。所以通用存在一对多的关系,也可以这样说:一对多是多对多的基本组成部分。

看下面的多对多的定义大家更会清楚”多对多“与“一对多”的关系:其中我们注意标签的特点就知道,它是定义了一个多对多关系,而不是。

Xml代码

Hibernate-mapping PUBLIC   "-//Hibernate/Hibernate Mapping DTD 2.0//EN"   "http://Hibernate.sourceforge.net/Hibernate-mapping-2.0.dtd">

dynamic-insert="true">

insert="true"column="name"/>

dynamic-insert="true">

insert="true"column="name"/>

<?xml version="1.0" encoding="UTF-8"?>  "-//Hibernate/Hibernate Mapping DTD 2.0//EN"

"http://Hibernate.sourceforge.net/Hibernate-mapping-2.0.dtd">

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

Java代码

packageorg.Hibernate.auction;

importjava.util.*;

/**

* * @author Administrator * * To change the template for this generated type

* comment go to * Window>Preferences>Java>Code Generation>Code and

* Comments

*/

publicclassTestA {

intid;

String name;

Set testBs = newHashSet();

publicTestA() {

}

publicTestA(intid) {

setId(id);

}

publicintgetId() {

returnid;

}

publicvoidsetId(intid) {

this.id = id;

}

publicString getName() {

returnname;

}

publicvoidsetName(String name) {

this.name = name;

}

publicSet getTestBs() {

returntestBs;

}

publicvoidsetTestBs(Set s) {

testBs = s;

}

publicvoidaddTestB(TestB tb) {

testBs.add(tb);

}

publicstaticvoidmain(String[] args) {

}

}

publicclassTestB {

intid;

String name;

Set testAs = newHashSet();

publicTestB() {

}

publicTestB(intid) {

setId(id);

}

publicintgetId() {

returnid;

}

publicvoidsetId(intid) {

this.id = id;

}

publicString getName() {

returnname;

}

publicvoidsetName(String name) {

this.name = name;

}

publicSet getTestAs() {

returntestAs;

}

publicvoidsetTestAs(Set s) {

testAs = s;

}

publicvoidaddTestA(TestA ta) {

testAs.add(ta);

}

publicstaticvoidmain(String[] args) {

}

}

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) {}}

测试代码:

Java代码

publicvoiddoTest()throwsException {

TestA a1 = newTestA(1);

TestA a2 = newTestA(2);

TestA a3 = newTestA(3);

TestB b1 = newTestB(1);

TestB b2 = newTestB(2);

TestB b3 = newTestB(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();

}

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如 下:

Java代码

/*   * Created on 2004-7-25

*   * To change the template for this generated file go to   * Window>Preferences>Java>Code Generation>Code and Comments   */packageorg.Hibernate.auction;

importjava.util.*;

/**

* * @author Administrator * * To change the template for this generated type

* comment go to * Window>Preferences>Java>Code Generation>Code and

* Comments

*/

publicclassTestB {

intid;

String name;

Set testAs = newHashSet();

publicTestB() {

}

publicTestB(intid) {

setId(id);

}

publicintgetId() {

returnid;

}

publicvoidsetId(intid) {

this.id = id;

}

publicString getName() {

returnname;

}

publicvoidsetName(String name) {

this.name = name;

}

publicSet getTestAs() {

returntestAs;

}

publicvoidsetTestAs(Set s) {

testAs = s;

}

publicvoidaddTestA(TestA ta) {

testAs.add(ta);

ta.addTestB(this);

}

publicstaticvoidmain(String[] args) {

}

}

/* * 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
    评论
Hibernate 的核心功能之一是 Java 对象和数据库表之间的映射,这是实现 ORM 的核心。Hibernate 提供了多种方式来进行对象和表之间的映射,包括 XML 映射文件、注解和 Java 代码映射等。无论使用哪种方式,Hibernate 的映射原理都是一致的。 Hibernate 的映射原理可以分为两个方面:对象属性和表列之间的映射、对象之间的关系映射。 1. 对象属性和表列之间的映射 在 Hibernate ,每个实体类都对应着一个数据库表,实体类的属性对应着数据库表的列。在使用 Hibernate 进行数据库操作时,Hibernate 会将实体对象的属性值映射到数据库表的列上,或将数据库表的列值映射到实体对象的属性上。Hibernate 的属性和表列之间的映射关系主要通过映射文件或注解来进行配置。 在映射文件,使用 <class> 标签定义实体类,使用 <property> 标签或 <id> 标签来定义属性,使用 <column> 标签来定义属性对应的数据库表列。例如: ```xml <class name="com.example.User" table="user"> <id name="id" type="long" column="id"> <generator class="identity"/> </id> <property name="name" column="name" type="string"/> <property name="age" column="age" type="integer"/> </class> ``` 在注解,使用 @Entity 标注实体类,使用 @Column 标注属性对应的数据库表列。例如: ```java @Entity @Table(name = "user") public class User { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) private Long id; @Column(name = "name") private String name; @Column(name = "age") private Integer age; // 省略 getter 和 setter 方法 } ``` 2. 对象之间的关系映射 在 Hibernate ,实体类之间可以存在多种关系,包括一对一、一对多、多对一和多对多等。Hibernate 通过映射文件或注解来定义实体类之间的关系映射关系。 例如,一对多关系可以通过在多的一方的实体类定义一个集合属性来表示。在映射文件,使用 <set> 标签定义集合属性,使用 <one-to-many> 标签定义集合元素对应的实体类。例如: ```xml <class name="com.example.Order" table="orders"> <id name="id" type="long" column="id"> <generator class="identity"/> </id> <property name="name" column="name" type="string"/> <set name="items" inverse="true" lazy="true" cascade="all"> <key column="order_id"/> <one-to-many class="com.example.OrderItem"/> </set> </class> <class name="com.example.OrderItem" table="order_items"> <id name="id" type="long" column="id"> <generator class="identity"/> </id> <property name="name" column="name" type="string"/> <property name="price" column="price" type="double"/> <many-to-one name="order" class="com.example.Order" column="order_id"/> </class> ``` 在注解,可以使用 @OneToMany 和 @ManyToOne 注解来定义一对多关系,使用 @JoinColumn 注解来定义外键。例如: ```java @Entity @Table(name = "orders") public class Order { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) private Long id; @Column(name = "name") private String name; @OneToMany(mappedBy = "order", cascade = CascadeType.ALL) private List<OrderItem> items; // 省略 getter 和 setter 方法 } @Entity @Table(name = "order_items") public class OrderItem { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) private Long id; @Column(name = "name") private String name; @Column(name = "price") private Double price; @ManyToOne @JoinColumn(name = "order_id") private Order order; // 省略 getter 和 setter 方法 } ``` 总之,Hibernate 的映射原理是将 Java 对象和数据库表之间的属性和关系进行映射,通过映射文件或注解来进行配置。Hibernate 支持多种关系映射,包括一对一、一对多、多对一和多对多等,开发人员可以根据需要选择合适的映射方式。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值