一对一主键关联不需要额外的表字段;如果两行是通过这种一对一关系相关联的,那么这两行就共享同样的主关键字值。所以如果你希望两个对象通过主键一对一关联,你必须确认它们被赋予同样的标识值!
比如说,对下面的Employee和Person进行主键一对一关联:
<one-to-one name="person" class="Person"/>
<one-to-one name="employee" class="Employee" constrained="true"/>
现在我们必须确保PERSON和EMPLOYEE中相关的字段是相等的。我们使用一个被成为foreign的特殊的hibernate标识符生成策略:
<class name="person" table="PERSON"> <id name="id" column="PERSON_ID"> <generator class="foreign"> <param name="property">employee</param> </generator> </id> ... <one-to-one name="employee" class="Employee" constrained="true"/> </class>
一个刚刚保存的Person实例被赋予和该Person的employee属性所指向的Employee实例同样的关键字值。
下面是居民与身份证的例子:
居民Person类
package org.hibernate.domain;
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;
}
}
身份证IdCard类:
package org.hibernate.domain;
public class IdCard {
private int id;
private Person person;
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public Person getPerson() {
return person;
}
public void setPerson(Person person) {
this.person = 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 package="org.hibernate.domain"> <class name="Person" table="person"> <id name="id"> <generator class="native" /> </id> <property name="name" /> <one-to-one name="idCard" /> </class> </hibernate-mapping>
<?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 package="org.hibernate.domain"> <class name="IdCard" table="idCard"> <id name="id"> <generator class="foreign"> <param name="property">person</param> </generator> </id> <one-to-one name="person" constrained="true" /> </class> </hibernate-mapping>
测试类:
package org.hibernate.test;
import org.hibernate.Session;
import org.hibernate.Transaction;
import org.hibernate.domain.IdCard;
import org.hibernate.domain.Person;
import org.hibernate.util.HibernateUtil;
public class OneToOne {
public static void main(String[] args) {
Person person = add();
person = queryPerson(person.getId());
queryIdCard(person.getIdCard().getId());
}
public static Person add() {
Session session = null;
Transaction tx = null;
try {
session = HibernateUtil.getSession();
IdCard idCard = new IdCard();
Person person = new Person();
person.setName("new person");
person.setIdCard(idCard);
idCard.setPerson(person);
tx = session.beginTransaction();
session.save(person);
session.save(idCard);
tx.commit();
return person;
} finally {
if (session != null)
session.close();
}
}
public static Person queryPerson(int id) {
Session session = null;
Transaction tx = null;
try {
session = HibernateUtil.getSession();
tx = session.beginTransaction();
Person person = (Person) session.get(Person.class, id);
tx.commit();
return person;
} finally {
if (session != null)
session.close();
}
}
public static IdCard queryIdCard(int id) {
Session session = null;
Transaction tx = null;
try {
session = HibernateUtil.getSession();
tx = session.beginTransaction();
IdCard idCard = (IdCard) session.get(IdCard.class, id);
tx.commit();
return idCard;
} finally {
if (session != null)
session.close();
}
}
}
控制台打印结果:
另一种方式是一个外键和一个惟一关键字对应,上面的Employee和Person的例子,如果使用这种关联方式,可以表达成:
<many-to-one name="person" class="Person" column="PERSON_ID" unique="true"/>
如果在Person的映射加入下面几句,这种关联就是双向的:
<one-to-one name"employee" class="Employee" property-ref="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 package="org.hibernate.domain"> <class name="Person" table="person"> <id name="id"> <generator class="native" /> </id> <property name="name" /> <one-to-one name="idCard" property-ref="person"/> </class> </hibernate-mapping>
<?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 package="org.hibernate.domain"> <class name="IdCard" table="idCard"> <id name="id"> <generator class="native" /> </id> <many-to-one name="person" column="person_id" unique="true" /> </class> </hibernate-mapping>