双向和单向的区别,其实不在数据库,而在加载方向。按照我们Person和IdCard的例子,单向是Person通过拥有IdCard的实例可以加载IdCard,而双向不但Person可以加载IdCard,还使IdCard通过拥有Person实例来加载Person。数据库还是原来的数据库(两个共享主键的表),不同的是在IdCard实体类中增加Person类型的变量和在IdCard.hbm.xml中增加了对该变量的配置。
/**
* 小结:插入时先插主表,后插副表.必须保证主表记录已经插入了,才能为副表提供引用需要的id.
*/
/**
* 测试加载操作
*/
/* Person p=(Person)session.load(Person.class, 1);
System.out.println(p);
System.out.println(p.getIdCard());*/
IdCard idCard=(IdCard)session.get(IdCard.class, 1);
System.out.println(idCard);
System.out.println(idCard.getPerson());
t.commit();
} catch (HibernateException e) {
e.printStackTrace();
t.rollback();
} finally {
HibernateUtils.closeSession(session);
}
}
}
1.实体模型:

2.关系模型:

3.实体类:
IdCard.java
public class IdCard {
private Integer id;
private String cardNo;
private Person person;
//一系列的setter.getter方法
@Override
public String toString() {
return "Idcard:"+cardNo;
}
}
private Integer id;
private String cardNo;
private Person person;
//一系列的setter.getter方法
@Override
public String toString() {
return "Idcard:"+cardNo;
}
}
Person.java
public class Person {
private Integer id;
private String name;
private IdCard idCard;
//一系列的setter.getter方法
@Override
public String toString() {
// TODO Auto-generated method stub
return "Person:"+name;
}
}
private Integer id;
private String name;
private IdCard idCard;
//一系列的setter.getter方法
@Override
public String toString() {
// TODO Auto-generated method stub
return "Person:"+name;
}
}
4.映射文件:
IdCard.hbm.xml
<class
name="com.sxt.hibernate.one2one.entity.IdCard"
table="sxt_hibernate_idCard">
<id name="id" length="4">
<generator class="native"></generator>
</id>
<property name="cardNo" length="10"></property>
<!-- one-to-one标签是为了加载 -->
<one-to-one name="person"></one-to-one>
</class>
<id name="id" length="4">
<generator class="native"></generator>
</id>
<property name="cardNo" length="10"></property>
<!-- one-to-one标签是为了加载 -->
<one-to-one name="person"></one-to-one>
</class>
Person.hbm.xml
<class
name="com.sxt.hibernate.one2one.entity.Person"
table="sxt_hibernate_person">
<id name="id" length="4">
<!-- person的主键来源于idCard,也就是共享idCard的主键 -->
<generator class="foreign">
<param name="property">idCard</param>
</generator>
</id>
<property name="name" length="10"></property>
<!--one-to-one标签的含义,指示Hibernate如何加载它的关联对象,默认根据主键加载。
constrained="true"的含义,表明当前主键上存在一个约束,person的主键作为外键参照了idCard,
并且要求关联属性不能为空
-->
<one-to-one name="idCard" constrained="true"></one-to-one>
</class>
<id name="id" length="4">
<!-- person的主键来源于idCard,也就是共享idCard的主键 -->
<generator class="foreign">
<param name="property">idCard</param>
</generator>
</id>
<property name="name" length="10"></property>
<!--one-to-one标签的含义,指示Hibernate如何加载它的关联对象,默认根据主键加载。
constrained="true"的含义,表明当前主键上存在一个约束,person的主键作为外键参照了idCard,
并且要求关联属性不能为空
-->
<one-to-one name="idCard" constrained="true"></one-to-one>
</class>
5.hibernate配置文件
hibernate.cfg.xml
限于篇幅,可以参照上一篇的该文件,此处就不再赘述。
6.测试方法:
public static
void main(String[] args) {
Session session = HibernateUtils.getSession();
Transaction t = session.beginTransaction();
try {
/**
* 测试插入操作
*/
/* IdCard idCard = new IdCard();
idCard.setCardNo("1234567890");
Person person = new Person();
person.setName("张三");
idCard.setPerson(person);
session.save(idCard);//这样的话,如果不在IdCard.hbm.xml的<one-to-one>中设置cascade="save-update"的话,会只保存上idCard,而保存不上关联属性person记录
//如果设置上cascade="save-update",则会先保存person记录,而由于person主键要引用idCard的id,此时idCard又没有保存呢,所以会报错org.hibernate.id.IdentifierGenerationException: attempted to assign id from null one-to-one property: idCard
*/
/* IdCard idCard = new IdCard();
idCard.setCardNo("1234567890");
Person person = new Person();
person.setName("张三");
idCard.setPerson(person);
session.save(person);//这样貌似关系已经建立好了,但是在存person时,它的主键关联属性idCard的id,而此时idCard为null,所以还是会报错org.hibernate.id.IdentifierGenerationException: attempted to assign id from null one-to-one property: idCard
*/
/* IdCard idCard = new IdCard();
idCard.setCardNo("1234567890");
Person person = new Person();
person.setName("张三");
person.setIdCard(idCard);
session.save(person);//这样,既建立好了关系,而且保存时还由person来维护关联关系,保存才是成功的
*/
Session session = HibernateUtils.getSession();
Transaction t = session.beginTransaction();
try {
/**
* 测试插入操作
*/
/* IdCard idCard = new IdCard();
idCard.setCardNo("1234567890");
Person person = new Person();
person.setName("张三");
idCard.setPerson(person);
session.save(idCard);//这样的话,如果不在IdCard.hbm.xml的<one-to-one>中设置cascade="save-update"的话,会只保存上idCard,而保存不上关联属性person记录
//如果设置上cascade="save-update",则会先保存person记录,而由于person主键要引用idCard的id,此时idCard又没有保存呢,所以会报错org.hibernate.id.IdentifierGenerationException: attempted to assign id from null one-to-one property: idCard
*/
/* IdCard idCard = new IdCard();
idCard.setCardNo("1234567890");
Person person = new Person();
person.setName("张三");
idCard.setPerson(person);
session.save(person);//这样貌似关系已经建立好了,但是在存person时,它的主键关联属性idCard的id,而此时idCard为null,所以还是会报错org.hibernate.id.IdentifierGenerationException: attempted to assign id from null one-to-one property: idCard
*/
/* IdCard idCard = new IdCard();
idCard.setCardNo("1234567890");
Person person = new Person();
person.setName("张三");
person.setIdCard(idCard);
session.save(person);//这样,既建立好了关系,而且保存时还由person来维护关联关系,保存才是成功的
*/
/**
* 小结:插入时先插主表,后插副表.必须保证主表记录已经插入了,才能为副表提供引用需要的id.
*/
/**
* 测试加载操作
*/
/* Person p=(Person)session.load(Person.class, 1);
System.out.println(p);
System.out.println(p.getIdCard());*/
IdCard idCard=(IdCard)session.get(IdCard.class, 1);
System.out.println(idCard);
System.out.println(idCard.getPerson());
t.commit();
} catch (HibernateException e) {
e.printStackTrace();
t.rollback();
} finally {
HibernateUtils.closeSession(session);
}
}
}