Hibernate一对一唯一外键关联映射(单向关联Person——>IDCard)
一对一唯一外键关联映射其实是多对一的特例,采用<many-to-one>标签来映射,指定多的一端unique为true,这样就限制了多的一端的多重性为一。
类图:
映射的数据库表:
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,所以在Person中应该有IDCard的引用。
IDCard.java:
public class IDCard { private Integer id; private String cardNo; 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; } }
注:因为是单向一对一关联,且从Person可以关联到IDCard但是从IDCard不能关联到Person,所以在IDCard中没有Person的引用。
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"/> </class> </hibernate-mapping>
注:IDCard一端是普通的javaBean,所以值是普通的属性映射。
测试通过Person添加IDCard:
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为瞬时状态的对象,所以不能级联保存。
测试二:
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对象时,我们就可以使其变为Persistent状态,从而两个对象都可以保存成功。