Hibernate数据关联是在Hibernate容器映射技术之上发展起来的。
Hibernate数据关联分为如下三种:
一对一(1:1)一个人拥有唯一身份证号
一对多(1:N)一个部门有很多员工
多对多(M:N)一个学生可以选很多课程,一门课程也可以有多个学生
一对一关联又包括如下两种类型:
1.主键关联(one-to-one)
即两张关联表通过主键形成一对一映射关系
2.唯一外键关联(也就是常说的多对一 :many-to-one)
1.先举例一个主键关联:
首先是数据库:
-- 删除表
DROP TABLE idcard ;
DROP TABLE person ;
-- 创建表
CREATE TABLE person
(
id VARCHAR(32) NOT NULL PRIMARY KEY ,
name VARCHAR(20) NOT NULL ,
age int
) ;
CREATE TABLE idcard
(
id VARCHAR(32) ,
serial VARCHAR(18) NOT NULL ,
expiry int ,
FOREIGN KEY(id) REFERENCES person(id) ON DELETE CASCADE
) ;
然后是POJO类:
package wjr.hibernate.demo23_26.associated11;
import java.util.Map;
public class Person {
private String id;
private String name;
private int age;
private IdCard idCard;
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public IdCard getIdCard() {
return idCard;
}
public void setIdCard(IdCard idCard) {
this.idCard = idCard;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
**************************************
package wjr.hibernate.demo23_26.associated11;
public class IdCard {
private String id; //在配置文件写好之后这个id属性可以直接删除,因为Idcard中的id属性关联实际上
//已经是通过person属性外键关联来完成了,也就是已经不再显示需要一个id属性了。
private String serial;
private int expiry;
private Person person;
public int getExpiry() {
return expiry;
}
public void setExpiry(int expiry) {
this.expiry = expiry;
}
public Person getPerson() {
return person;
}
public void setPerson(Person person) {
this.person = person;
}
public String getSerial() {
return serial;
}
public void setSerial(String serial) {
this.serial = serial;
}
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
}
接着就是生成映射文件:
<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
<!--
Mapping file autogenerated by MyEclipse - Hibernate Tools
-->
<hibernate-mapping>
<class name="wjr.hibernate.demo23_26.associated11.Person" table="person" lazy="true>
<id name="id" type="java.lang.String">
<column name="id" length="32" />
<generator class="uuid.hex"></generator>
</id>
<property name="name" type="java.lang.String">
<column name="name" length="20" not-null="true" />
</property>
<property name="age" type="java.lang.Integer">
<column name="age" />
</property>
<one-to-one name="idCard"
class="wjr.hibernate.demo23_26.associated11.IdCard" cascade="all"
<!--
<one-to-one>元素的cascade属性表明操作是否从父对象级联到被关联的对象, 它
的取得可以是以下几种:
none:在保存,删除或修改当前对象时,不对其附属对象(关联对象)进行级联
操作。它是默认值。
save-update:在保存,更新当前对象时,级联保存,更新附属对象(临时对象,
游离对象)。
delete:在删除当前对象时,级联删除附属对象。
all:所有情况下均进行级联操作,即包含save-update和delete操作。
delete-orphan:删除和当前对象解除关系的附属对象。
<one-to-one>元素的fetch属性的可选值是join和select,默认是select。
当fetch属性设定为join时,表示连接抓取(Join fetching):Hibernate通过
在Select语句中使用outer join(外连接)来获得对象的关联实例或者关联集合。
当fetch属性设定为select时,表示查询抓取(Select fetching):需要另外发
送一条Select语句抓取当前对象的关联实体或集合.
-->
outer-join="true">
</one-to-one>
</class>
</hibernate-mapping>
**********************************************
<!--one-to-one需要设置constrained节点属性。作用就是告知Hibernate当前表
主键上存在一个约束。
-->
<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
<!--
Mapping file autogenerated by MyEclipse - Hibernate Tools
-->
<hibernate-mapping>
<class name="wjr.hibernate.demo23_26.associated11.IdCard" table="idcard" catalog="huanhuan">
<id name="id" column="id" type="java.lang.String">
<generator class="foreign">
<param name="property">person</param>
</generator><!-- id使用外键(foreign)生成机制,引用代号为person的对象
的主键作为idcard表的主键和外键。同时person在下面的<one-to-one>中进行了定义 -->
</id>
<one-to-one name="person"
class="wjr.hibernate.demo23_26.associated11.Person" constrained="true">
</one-to-one><!-- constrained="true"表示idcard引用了person的主键作为外键。 -->
<property name="serial" type="java.lang.String">
<column name="serial" length="18" not-null="true" />
</property>
<property name="expiry" type="java.lang.Integer">
<column name="expiry" not-null="true" />
</property>
</class>
</hibernate-mapping>
最后就是操作类了:
package wjr.hibernate.demo23_26.associated11;
import org.hibernate.Session;
import org.hibernate.cfg.Configuration;
import wjr.hibernate.demo23_26.associated11.*;
public class PersonIdCardOperation {
private Session session;
public PersonIdCardOperation() {
this.session = new Configuration().configure().buildSessionFactory()
.openSession();
}
public void insert(Person per) {
this.session.save(per);
this.session.beginTransaction().commit();
}
public static void main(String[] args) {
PersonIdCardOperation po = new PersonIdCardOperation();
Person p = new Person();
p.setName("yaya");
p.setAge(3);
IdCard ic = new IdCard();
ic.setExpiry(20);
ic.setSerial("511324198306102259");
p.setIdCard(ic);
ic.setPerson(p);
po.insert(p);
}
}
2.唯一外键关联:
请见多对一示例。