Hibernate一对一唯一外键关联映射(双向关联Person<——>IDCard)。
类图:
映射的数据库表:
Person.java:
public class Person { private Integer id; private String name; /*定义Person和IDCard的关系(双向一对一唯一外键关联)*/ private IDCard idCard; public Integer getId() { return id; } public void setId(Integer 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中有IDCard的引用,IDCard中也有Person的引用。
IDCard.java:
public class IDCard { private Integer id; private String cardNo; /* IDCard和Person的关系(双向一对一唯一外键关联) */ private Person person; public Integer getId() { return id; } public void setId(Integer id) { this.id = id; } public String getCardNo() { return cardNo; } public void setCardNo(String cardNo) { this.cardNo = cardNo; } public Person getPerson() { return person; } public void setPerson(Person person) { this.person = person; } }
注:因为是一对一唯一外键关联,所以IDCard中有Person的引用,Person中也有IDCard的引用。
Person.hbm.xml:
<?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="com.lixue.bean"> <class name="Person" table="t_person"> <id name="id"> <generator class="native"/> </id> <property name="name"/> <!-- 一对一唯一外键关联映射其实是多对一的特例,我们使用many-to-one 但是指定多的一端unique为true,这样就限制了多的一端的多重性 --> <many-to-one name="idCard" unique="true"/> </class> </hibernate-mapping>
注:一对一唯一外键关联映射其实是多对一的特例,我们使用many-to-one来映射,但是指定多的一端unique为true,这样就限制了多的一端的多重性。
IDCard.hbm.xml:
<?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="com.lixue.bean"> <class name="IDCard" table="t_idCard"> <id name="id"> <generator class="native"/> </id> <property name="cardNo"/> <!-- 映射一对一关联 property-ref表示要引用的属性为idCard--> <one-to-one name="person" property-ref="idCard"/> </class> </hibernate-mapping>
注:在IDcard这一段也要指定one-to-one映射。
测试方法:
public void testSave1(){ /*定义Session和事物*/ Session session = null; Transaction transaction = null; try { /*获取Session并开启事物*/ session = HibernateUtils.getSession(); transaction = session.beginTransaction(); /*创建身份证并设置属性*/ IDCard idCard = new IDCard(); idCard.setCardNo("367578677545348879"); /*创建人并设置属性*/ Person person = new Person(); person.setName("习近平"); /*建立关联*/ person.setIdCard(idCard); /** * 会抛出TransientObjectException异常 * 因为IDCard对象此时为Transient对象,数据库中 * 没有与之对应的数据导致出错 */ session.save(person); /*提交事物*/ transaction.commit(); } catch (Exception e) { e.printStackTrace(); transaction.rollback(); } finally{ HibernateUtils.closeSession(session); } }
注:抛异常的原因是因为IDCard对象此时还是Transient状态,数据库中没有与之对应的数据。
测试方法二:
public void testSave3(){ /*定义Session和事物*/ Session session = null; Transaction transaction = null; try { /*获取Session并开启事物*/ session = HibernateUtils.getSession(); transaction = session.beginTransaction(); /*创建身份证并设置属性*/ IDCard idCard = new IDCard(); idCard.setCardNo("367578677545348879"); /*创建人并设置属性*/ Person person = new Person(); person.setName("习近平"); /*建立关联*/ person.setIdCard(idCard); /** * 不会抛出TransientObjectException异常 * 因为我们显示的调用了save方法使得IDCard对象变为Persistent对象,数据库中 * 有与之对应的数据 */ session.save(idCard); session.save(person); /*提交事物*/ transaction.commit(); } catch (Exception e) { e.printStackTrace(); transaction.rollback(); } finally{ HibernateUtils.closeSession(session); } }
注:这样可以保存成功,因为我们显示的保存了IDCard对象,使IDCard对象由Transient对象变为Persistent状态。