Hibernate 学习经验之谈-(四)关联映射

来源:互联网 发布:知乎2016 编辑:程序博客网 时间:2024/05/22 17:48

摘要:

(待编写)

        Hibernate 是一个ORM 框架,它的重点就是对象之间的关系模型,维护对象之间的关系是hibernate 的核心内容,也是这个框架中相对比较难的一点。如果能够灵活地运用好这个框架,必须熟悉对象之间的联系。Hibernate 中的主要有三种对象的关系:One to One(一对一关联映射);One to Many (一对多关联映射);Many to Many (关联映射)。 每一种映射又分单向和双向。在数据库中关系表之间的关系只有一种,就是外键关联,hibernatre的对象映射就是建立在数据库外键关联之上。

要掌握hibernate的关联映射,必须要分析hibernate 在使用对象关联时生成的DDL语句,理解每一种映射在数据库中的对应处理方式。

单向关联与双向关联的区别

    对象通过组合的方式来表达的类之间的关系,并在hbm文件或者注解上做出明确的说明。 

           单向可以理解为在两个有关联的对象实体中,只在一方中说明关联关系,对象只能在一方导向到另一方。

           双向可以理解为在两个有关联的对象实体中,双方都有说明关联关系的配置,对象之间可以互相访问到对方。

          导向的意思是说在对象的关联字段访问到关联的对象的信息,双向和单向在数据库层级的实现基本一样。

           对于设置了双向关联的实体,最好的做法就是在其中一方使用mappedBy 指定主导关系,不然会出现冗余的数据字段。原则是在1-1 可以任意设一方,1-N 在N方设置mappedBy,N-N 的在任意一方设置。mappedBy 是关联注解的一个属性,mappedBy="xxx",xxx 为主导关系的getXXX对应的值。例如mappedBy=“person”  person 对应的不是下文中的person 属性,而是对应getter 中getXXX,的“XXX”位置的值,person 对应getPerson();


一.One to One(一对一关联映射)

1.解析:

例如,一个人只能有一张身份证,一张身份证只能对应一个人;这两个对象之间就是属于一对一;一对一是三种关系中最简单的一种。


2.种类:主键关联,唯一外键关联;

2.1 主键关联:两个对象采用一样的主键值来表明他们之间是属于一对一的关系,这种方法是基本不用的。

2.2 外键关联:两个对象采用外键来表示两个之间的联系。

3.配置方式(只讲外键关联)

3.1单向配置

Person

package com.hwj.model;import javax.persistence.Entity;import javax.persistence.GeneratedValue;import javax.persistence.Id;import javax.persistence.OneToOne;import javax.persistence.Table;import org.hibernate.annotations.DynamicUpdate;@Table(name="t_person")@Entity@DynamicUpdatepublic class Person {private int id;private String nickName;//关联字段private IDCard idCard;@Id@GeneratedValuepublic int getId() {return id;}@OneToOnepublic IDCard getIdCard() {return idCard;}public String getNickName() {return nickName;}public void setId(int id) {this.id = id;}public void setIdCard(IDCard idCard) {this.idCard = idCard;}public void setNickName(String nickName) {this.nickName = nickName;}}

IDCard

<pre name="code" class="java">package com.hwj.model;import javax.persistence.Entity;import javax.persistence.GeneratedValue;import javax.persistence.Id;import javax.persistence.OneToOne;import javax.persistence.Table;import org.hibernate.annotations.DynamicUpdate;@Entity@Table(name="t_idcard")@DynamicUpdatepublic class IDCard {private int id;private String name;private String idNo;@Id@GeneratedValuepublic int getId() {return id;}public String getIdNo() {return idNo;}public String getName() {return name;}public void setId(int id) {this.id = id;}public void setIdNo(String idNo) {this.idNo = idNo;}public void setName(String name) {this.name = name;}}


hibernate 生成的sql语句

Hibernate:     create table t_idcard (        id integer not null auto_increment,        idNo varchar(255),        name varchar(255),        primary key (id)    )Hibernate:     create table t_person (        id integer not null auto_increment,        nickName varchar(255),        idCard_id integer,        primary key (id)    )Hibernate:     alter table t_person         add constraint FK_iwf0ex84epvoh2ndq1axpceg9         foreign key (idCard_id)         references t_idcard (id)


3.2 双向配置


Person

package com.hwj.model;import javax.persistence.Entity;import javax.persistence.GeneratedValue;import javax.persistence.Id;import javax.persistence.OneToOne;import javax.persistence.Table;import org.hibernate.annotations.DynamicUpdate;@Table(name="t_person")@Entity@DynamicUpdatepublic class Person {private int id;private String nickName;//关联字段private IDCard idCard;@Id@GeneratedValuepublic int getId() {return id;}@OneToOne(mappedBy="pserson")public IDCard getIdCard() {return idCard;}public String getNickName() {return nickName;}public void setId(int id) {this.id = id;}public void setIdCard(IDCard idCard) {this.idCard = idCard;}public void setNickName(String nickName) {this.nickName = nickName;}}


IDCard

package com.hwj.model;import javax.persistence.Entity;import javax.persistence.GeneratedValue;import javax.persistence.Id;import javax.persistence.OneToOne;import javax.persistence.Table;import org.hibernate.annotations.DynamicUpdate;@Entity@Table(name="t_idcard")@DynamicUpdatepublic class IDCard {private int id;private String name;private String idNo;private Person pserson;@Id@GeneratedValuepublic int getId() {return id;}public String getIdNo() {return idNo;}public String getName() {return name;}@OneToOnepublic Person getPserson() {return pserson;}public void setId(int id) {this.id = id;}public void setIdNo(String idNo) {this.idNo = idNo;}public void setName(String name) {this.name = name;}public void setPserson(Person pserson) {this.pserson = pserson;}}



hibernate 生成的sql语句

Hibernate:     create table t_idcard (        id integer not null auto_increment,        idNo varchar(255),        name varchar(255),        pserson_id integer,        primary key (id)    )Hibernate:     create table t_person (        id integer not null auto_increment,        nickName varchar(255),        primary key (id)    )Hibernate:     alter table t_idcard         add constraint FK_pdvviqxfv7qwech66rqm08830         foreign key (pserson_id)         references t_person (id)


总结,使用主要使用外键关联,在双方设置了双向关联的时候,进行mappedBy 设置。 

二.One to Many  与 Many to One

      其实一对多,还有多对一,都只是在不同的角度来看,但是映射产生的结果可能会不一样。这里使用Group 组与 User 成员来做举例。

      1.单向映射

        1.1 One to Many (一对多 )

Group 映射

package com.hwj.model;import java.util.List;import javax.persistence.Entity;import javax.persistence.GeneratedValue;import javax.persistence.Id;import javax.persistence.JoinColumn;import javax.persistence.OneToMany;import javax.persistence.Table;import org.hibernate.annotations.DynamicUpdate;import org.hibernate.annotations.UpdateTimestamp;@Entity@Table(name="t_group")@DynamicUpdatepublic class Group {private int id;private String name;private List<User> users;@Id@GeneratedValuepublic int getId() {return id;}public String getName() {return name;}@OneToMany@JoinColumn(name="group_id")public List<User> getUsers() {return users;}public void setId(int id) {this.id = id;}public void setName(String name) {this.name = name;}public void setUsers(List<User> users) {this.users = users;}}


       User 的映射

package com.hwj.model;import javax.persistence.Entity;import javax.persistence.GeneratedValue;import javax.persistence.Id;import javax.persistence.ManyToOne;import javax.persistence.Table;import org.hibernate.annotations.DynamicUpdate;@Entity@Table(name="t_user")@DynamicUpdatepublic class User {private int id;private String name;@Id@GeneratedValuepublic int getId() {return id;}public String getName() {return name;}public void setId(int id) {this.id = id;}public void setName(String name) {this.name = name;}}


产生的sql语句

Hibernate:     create table t_group (        id integer not null auto_increment,        name varchar(255),        primary key (id)    )Hibernate:     create table t_user (        id integer not null auto_increment,        name varchar(255),        group_id integer,        primary key (id)    )Hibernate:     alter table t_user         add constraint FK_e5f24mh6aryt9hsy99oydps6g         foreign key (group_id)         references t_group (id)



注意,假如在一对多关联映射中只使用了 One to Many 的话,hibernate 就会发生把One to Many 当成 many to many 方式生成sql 语句,生成的语句中会存在中间表。但是在关联字段添加@joinColumn(name="外键名称") ,j就可以避免这种情况生成正确的sql语句。


     1.2.many to one

          注:many to one 配置方式十分方便,只要在多的一方在关联字段加上 @ManyToOne 就可以正确在多一方生成外键约束。


2.双向关联

注;双向关联中需要在one 的一方设置mappedBy ,在many to one 的一方没有这个属性。设置完后就是实现了对数据的双向导航。


三.Many to Many (关联映射)

1.单向映射

只要在关联字段上添加@ManyToMany 就可以实现多对多单向映射。

2.双向映射

双向映射的时候一定要设置在任意一方设置mappedBy 这样才能不会执行重复的sql语句。

3.表生成

     多对多表映射是采用中间表的方式来实现映射的,中间表字段的修改可以使用@JoinTable来实现。这个注解可以修改中间表的表名,表中的外键字段。

            @JoinTable(

          joinColumns={@JoinColumn(name="本对象的外键引用字段名")},  //为数组的原因是考虑到联合主键的情况

         inverseJoinColumns={@JoinColumn(name="另外的一方的对象外键引用的字段名")}     //为数组的原因是考虑到联合主键的情况

         )




0 0
原创粉丝点击