ITEEDU

Hibernate-one-to-one单向映射

one-to-one

one-to-one是一对一映射关系,如人和身份证之间的关系,一个人只能有一个身份证号,一个身份证号只能属于一个人。

一对一又可分为单向映射和双向映射,映射实现可以分为主键映射和外键映射。结合一下就成了四种:

  1. 一对一单向主键映射。
  2. 一对一双向主键映射。
  3. 一对一单向外键映射。
  4. 一对一双向外键映射。

一对一单向主键映射

一对一单向主键映射实现思想是让一个表的主键为关联的外键,因为外键是另一个表的主键并且为一,所以可以作为主键来用。

如人和身份证的关系,人必定有一个外键关联身份证表主键,可以这个外键作为人的主键。这样就形成了人用身份证表的主键作为自己主键的特殊形式。

身份证类

package com.iteedu.hibernate;

public class IdCard {
	private int id;
	private String cardNo;

	public int getId() {
		return id;
	}

	public void setId(int id) {
		this.id = id;
	}

	public String getCardNo() {
		return cardNo;
	}

	public void setCardNo(String cardNo) {
		this.cardNo = cardNo;
	}
}

 身份证类映射文件

<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC 
	"-//Hibernate/Hibernate Mapping DTD 3.0//EN"
	"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
<hibernate-mapping>
	<class name="com.iteedu.hibernate. IdCard" table="t_idcard">
		<id name="id">
			<generator class="native"/>
		</id>
		<property name="cardNo"/>
	</class>
</hibernate-mapping>

Person类

package com.iteedu.hibernate;

public class Person {
	private int id;
	private String name;
	private IdCard idCard; 

	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 IdCard getIdCard() {
		return idCard;
	}

	public void setIdCard(IdCard idCard) {
		this.idCard = idCard;
	}
}

 Person类映射文件

<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC 
	"-//Hibernate/Hibernate Mapping DTD 3.0//EN"
	"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
<hibernate-mapping>
	<class name="com.iteedu.hibernate.Person" table="t_person">
		<id name="id">
            <!-- person的主键来源idCard,也就是共享idCard的主键 -->
			<generator class="foreign">
				<param name="property">idCard</param>
			</generator>
		</id>
		<property name="name"/>
		<one-to-one name="idCard" constrained="true"/>
	</class>
</hibernate-mapping>

由于Person的主键为身份证的主键所以要用foreign,foreign使用另外一个相关联的对象的标识符。通常和<one-to-one>联合起来使用。

one-to-one标签的含义,指示hibernate怎么加载它的关联对象,默认根据主键加载, constrained=”true”,        表明当前主键上存在一个约束,person的主键作为外键参照了idCard。

调用示例

session.beginTransaction();

IdCard idCard = new IdCard();
idCard.setCardNo("21341341234123");

Person person = new Person();
person.setName("ITEEDU");
person.setIdCard(idCard);

//不会出现TransientObjectException异常
//因为一对一主键关联映射中,默认了cascade属性
session.save(person);

 一对一双向主键映射

在IdCard中添加Person属性:

private Person person;
public Person getPerson() {
	return person;
}

public void setPerson(Person person) {
	this.person = person;
}

在配制文件中加入关联:

<one-to-one name="person"/>

这样加载card时就会加载人员信息了。

session.beginTransaction();
IdCard idCard = (IdCard)session.load(IdCard.class, 1);
System.out.println("idcard.cardNo=" + idCard.getCardNo());
System.out.println("idcard.person.name=" + idCard.getPerson().getName());
session.getTransaction().commit();

 一对一单向外键关联

一对唯一外键关联映射是多对一关联映射的特例,可以通过限制many-to-one来实现的。mang-to-one中的关联外键是可以重复的,如多个人属于一个组。如果限制其唯一性就形成了一对一关系,因为没有一个身份证id关联多个人。

采用<many-to-one>标签,指定多的一端的unique=true,这样就限制了多的一端的多重性为一。通过这种手段映射一对一唯一外键关联。

实现如下:

<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC 
	"-//Hibernate/Hibernate Mapping DTD 3.0//EN"
	"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
<hibernate-mapping>
	<class name="com.iteedu.hibernate.Person" table="t_person">
		<id name="id">
			<generator class="native"/>
		</id>
		<property name="name"/>
		<many-to-one name="idCard" unique="true"/>
	</class>
</hibernate-mapping>

注意:主键id不能再用foreign了。

一对一双向外键关联

一对一唯一外键关联双向,需要在另一端(idcard),添加<one-to-one>标签,指示hibernate如何加载其关联对象,默认根据主键加载person,外键关联映射中,因为两个实体采用的是person的外键维护的关系,所以不能指定主键加载person,而要根据person的外键加载。

修改IdCard相关文件。

添加Person属性:

private Person person;
public Person getPerson() {
	return person;
}

public void setPerson(Person person) {
	this.person = person;
}

 映射文件添加:

<one-to-one name="person" property-ref="idCard"/>

其中property-ref为指定关联类的属性名,这个属性将会和本类的主键相对应。如果没有指定,会使用对方关联类的主键。

注意:不是数据库中的列名,是类中的属性名。