摘要:
(待编写)
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
@DynamicUpdate
public class Person {
private int id;
private String nickName;
//关联字段
private IDCard idCard;
@Id
@GeneratedValue
public int getId() {
return id;
}
@OneToOne
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
<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")
@DynamicUpdate
public class IDCard {
private int id;
private String name;
private String idNo;
@Id
@GeneratedValue
public 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
@DynamicUpdate
public class Person {
private int id;
private String nickName;
//关联字段
private IDCard idCard;
@Id
@GeneratedValue
public 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")
@DynamicUpdate
public class IDCard {
private int id;
private String name;
private String idNo;
private Person pserson;
@Id
@GeneratedValue
public int getId() {
return id;
}
public String getIdNo() {
return idNo;
}
public String getName() {
return name;
}
@OneToOne
public 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")
@DynamicUpdate
public class Group {
private int id;
private String name;
private List<User> users;
@Id
@GeneratedValue
public 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")
@DynamicUpdate
public class User {
private int id;
private String name;
@Id
@GeneratedValue
public 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)
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="另外的一方的对象外键引用的字段名")} //为数组的原因是考虑到联合主键的情况
)