`
woshixushigang
  • 浏览: 562917 次
  • 性别: Icon_minigender_1
  • 来自: 北京
社区版块
存档分类

hibernate一对多关系采用外键映射时使用inverse的几种情况

阅读更多

hibernate关系的维护比较头疼,遂总结下做个备份。

什么时候维护关系:当关联双方对象有一方的属性发生变化时。

举例:一个用户有多个账户,类User和类Account是一对多的双向关联关系。

User类:

public class User {

private Long oid;

private String uid;

private String name;

//关联属性

private Set accts = new HashSet();

......

}

Account类:

public class Account {

private Long oid;

private String acctNo;

private double bal;

//关联属性

private User owner;

......

}

mq_user:

mysql> desc mq_user;

+-----------+--------------+------+-----+---------+----------------+

| Field | Type | Null | Key | Default | Extra |

+-----------+--------------+------+-----+---------+----------------+

| OID | bigint(20) | NO | PRI | NULL | auto_increment |

| USER_ID | varchar(255) | NO | UNI | NULL | |

| USER_NAME | varchar(255) | NO | | NULL | |

+-----------+--------------+------+-----+---------+----------------+

mq_acct2

mysql> desc mq_acct2;

+--------+--------------+------+-----+---------+----------------+

| Field | Type | Null | Key | Default | Extra |

+--------+--------------+------+-----+---------+----------------+

| OID | bigint(20) | NO | PRI | NULL | auto_increment |

| ACCTNO | varchar(255) | NO | UNI | NULL | |

| BAL | double | NO | | NULL | |

| FID | bigint(20) | YES | MUL | NULL | |

+--------+--------------+------+-----+---------+----------------+

映射文件:

User.hbm.xml:

<set name = "accts" inverse = "false" >

<key column="FID" />

<one-to-many class="Account" />

</set>

 

Account.hbm.xml:

<many-to-one name = "owner"

class = "User"

column = "FID"/>

 

 

如果:Session s = HbnUtil.getSession();

s.beginTransaction();

Account acct1 = new Account("a01", 5000.0);

User user = new User("u01","jack");

user.getAccts().add(acct1);

s.save(user);

s.save(acct1);

s.getTransaction().commit();

结果:Hibernate:

insert

into

mq_user

(USER_ID, USER_NAME)

values

(?, ?)

Hibernate:

insert

into

mq_acct2

(ACCTNO, BAL, FID)

values

(?, ?, ?)

Hibernate:

update

mq_acct2

set

FID=?

where

OID=?

 

说明:一对多双向关联中默认多的一方inverse=”false”,也就是说由多的一方维护关系。

这里把一的一方的inverse也改为false,并且在代码中不写acct1.setOwner(user)是为了测试一的一方是如何维护关系的。

在执行了insert into 语句以后,紧接着执行的update语句就是一的一方在维护关系。

从执行的过程还可以看出,维护关系的动作实际上是update而不是insert操作。

总结:1,多的一方总是维护且必须维护关系(many-to-one中没有inverse属性),一的一方可以选择维护或不维护。

---------------------------------------------------------------------

如果:Session s = HbnUtil.getSession();

s.beginTransaction();

Account acct1 = new Account("a01", 5000.0);

User user = new User("u01","jack");

user.getAccts().add(acct1);

s.save(user);

s.getTransaction().commit();

结果:Hibernate:

insert

into

mq_user

(USER_ID, USER_NAME)

values

(?, ?)

Hibernate:

update

mq_user

set

USER_ID=?,

USER_NAME=?

where

OID=?

Hibernate:

update

mq_acct2

set

FID=?

where

OID=?

org.hibernate.TransientObjectException:

 

说明:去掉了对acct1的保存。抛异常。

inverse是关系维护而不是级联操作(通过配置cascade属性可以让user被保存时级联acct1一起被保存),关系维护只会update

总结:2,关系维护只做update,不搞级联,所以要注意维护的数据是否已经在数据库中。

除非做了级联create或者数据库中有被维护的数据,否则是要抛异常滴。

---------------------------------------------------------------------

如果:Account acct1 = new Account("a01", 5000.0);

User user = new User("u01","jack");

user.getAccts().add(acct1);

s.save(user);

s.save(acct1);

user.setName("aaaaa");

结果:Hibernate:

insert

into

mq_user

(USER_ID, USER_NAME)

values

(?, ?)

Hibernate:

insert

into

mq_acct2

(ACCTNO, BAL, FID)

values

(?, ?, ?)

Hibernate:

update

mq_user

set

USER_ID=?,

USER_NAME=?

where

OID=?

Hibernate:

update

mq_acct2

set

FID=?

where

OID=?

说明:因为user是一个持久化对象(session保存过),所以在user属性发生改变时,session会监测user属性是否改变并在改变后自动执行update mq_user。但不管acct1属性是否改变,也不管username改变是否影响到了他和acct1的关系,都会再维护一次。

---------------------------------------------------------------------

如果:Account acct1 = new Account("a01", 5000.0);

User user = new User("u01","jack");

user.getAccts().add(acct1);

s.save(user);

s.save(acct1);

acct1.setBal(999);

结果:

Hibernate:

insert

into

mq_user

(USER_ID, USER_NAME)

values

(?, ?)

Hibernate:

insert

into

mq_acct2

(ACCTNO, BAL, FID)

values

(?, ?, ?)

Hibernate:

update

mq_acct2

set

ACCTNO=?,

BAL=?,

FID=?

where

OID=?

Hibernate:

update

mq_acct2

set

FID=?

where

OID=?

说明:因为acct1是持久化对象,所以session在发现acct1bal发生改变后会自动执行

update mq_acct2语句。随后负责维护关系的user一方会再维护一次关系。

------------------------------------------------------------------------------------

<!--[endif]-->

如果:Account acct1 = new Account("a01", 5000.0);

User user = new User("u01","jack");

user.getAccts().add(acct1);

acct1.setOwner(user);

s.save(user);

s.save(acct1);

acct1.setBal(999);

结果:Hibernate:

insert

into

mq_user

(USER_ID, USER_NAME)

values

(?, ?)

Hibernate:

insert

into

mq_acct2

(ACCTNO, BAL, FID)

values

(?, ?, ?)

Hibernate:

update

mq_acct2

set

ACCTNO=?,

BAL=?,

FID=?

where

OID=?

Hibernate:

update

mq_acct2

set

FID=?

where

OID=?

说明:如果双方是双向关联又各自都维护关系,那么当需要维护时会各自维护一次。

总结:3,实际运行时的对象如果不知道对方对象的存在(没有关联)就不会维护关系。

4,只要任意一方属性变了就维护,不管这个变更是否影响到了关系。

分享到:
评论

相关推荐

    Hibernate_Annotation关联映射

    和其它许多批注一样,在多对多关联中很多值是自动生成,党双向多对多关联中没有定义任何物理映射时,Hibernate根据以下规则生成相应的值,关联表名:主表表名+下划线+从表表名,关联到主表的外键名:主表名+下划线+...

    精通 Hibernate:Java 对象持久化技术详解(第2版).part2

     7.1 建立多对一的单向关联关系  7.1.1 元素的not-null属性  7.1.2 级联保存和更新  7.2 映射一对多双向关联关系  7.2.1 元素的inverse属性  7.2.2 级联删除  7.2.3 父子关系  7.3 映射一对多双向自身关联...

    Hibernate注释大全收藏

    这种策略支持双向的一对多关联,但不支持 IDENTIFY 生成器策略,因为ID必须在多个表间共享。一旦使用就不能使用AUTO和IDENTIFY生成器。 每个类层次结构一张表 @Entity @Inheritance(strategy=InheritanceType....

    精通 Hibernate:Java 对象持久化技术详解(第2版).part4

     7.1 建立多对一的单向关联关系  7.1.1 元素的not-null属性  7.1.2 级联保存和更新  7.2 映射一对多双向关联关系  7.2.1 元素的inverse属性  7.2.2 级联删除  7.2.3 父子关系  7.3 映射一对多双向自身关联...

    精通 Hibernate:Java 对象持久化技术详解(第2版).part3

     7.1 建立多对一的单向关联关系  7.1.1 元素的not-null属性  7.1.2 级联保存和更新  7.2 映射一对多双向关联关系  7.2.1 元素的inverse属性  7.2.2 级联删除  7.2.3 父子关系  7.3 映射一对多双向自身关联...

    精通 Hibernate:Java 对象持久化技术详解(第2版).part1.rar

     7.1 建立多对一的单向关联关系  7.1.1 元素的not-null属性  7.1.2 级联保存和更新  7.2 映射一对多双向关联关系  7.2.1 元素的inverse属性  7.2.2 级联删除  7.2.3 父子关系  7.3 映射一对多双向自身关联...

    hibernate总结

    Hibernate映射多对多(两个一对多实现多对多) 表:材料表和产品表多对多,在数据库中有中间表即产品材料表用来存放两个表之间的关系 Java类:材料PO,产品PO,中间PO,中间PO的复合主键类(由于是两个一对多形成的多对...

    jdbc基础和参考

    一般在做双向多对一(一对多)关联关系映射的时候,一般会设置让一的一方放弃对关联关系的维护,以减少不必要的更新语句 一对一: 基于外键的一对一 Wife Husband id id name name h_id references Husband...

    BOS 技术整理

    @OneToMany(mappedBy 相当于 inverse ) @ManyToOne 结合 @JoinColumn 添加一列外键 @ManyToMany 一方写 mappedBy 放弃外键维护、另一方 @JoinTable 维护中间表 收派标准修添加能实现 html 请求 后台...

Global site tag (gtag.js) - Google Analytics