继之前的工程,现在来看下如何实现双向映射。
就是用IdCard能找到Person,也能用Person找到IdCard
前面的IdCard和Person的实体类代码没有态度的变化,主要是因为要实现双向映射,所以要在两个类中分别持有另一方对象。
主要看下两个配置文件:
Person.hbm.xml
<?xml version="1.0" encoding="UTF-8"?> <!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.mp.hibernate.Person" table="t_person"> <id name="id"> <generator class="foreign"> <param name="property">idCard</param> </generator> </id> <property name="name"></property> <one-to-one name="idCard" constrained="true"></one-to-one> </class> </hibernate-mapping>
这个文件与上一个工程没有变化,现在主要是添加Person到IdCard的映射,所以看下
IdCard.hbm.xml
<?xml version="1.0" encoding="UTF-8"?> <!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.mp.hibernate.IdCard" table="t_idcard"> <id name="id"> <generator class="native"></generator> </id> <property name="cardNo"></property> <one-to-one name="person"></one-to-one> </class> </hibernate-mapping>
也就是说实现双向映射就在IdCard的配置文件中再添加一个one-to-one标签
<one-to-one name="person"></one-to-one>
再看下测试类:
package com.mp.hibernate; import org.hibernate.Session; import junit.framework.TestCase; public class One2OneTest extends TestCase { public void testSave1() { Session session = null; try { session = HibernateUtils.getSession(); session.beginTransaction(); IdCard idCard = new IdCard(); idCard.setCardNo("234589389894893384"); Person person = new Person(); person.setName("刘德华"); person.setIdCard(idCard); //不会出现TransientObejectException异常 //因为一对一主键关联映射中,默认了cascade属性 session.save(person); session.getTransaction().commit(); } catch (Exception e) { e.printStackTrace(); session.getTransaction().rollback(); } finally { HibernateUtils.closeSession(session); } } public void testLoad() { Session session = null; try { session = HibernateUtils.getSession(); session.beginTransaction(); Person person = (Person)session.load(Person.class, 1); System.out.println("person.name=" + person.getName()); System.out.println("idcard.cardNo" + person.getIdCard().getCardNo()); session.getTransaction().commit(); } catch (Exception e) { e.printStackTrace(); session.getTransaction().rollback(); } finally { HibernateUtils.closeSession(session); } } public void testLoad2() { Session session = null; try { session = HibernateUtils.getSession(); session.beginTransaction(); IdCard idCard = (IdCard)session.load(IdCard.class, 1); System.out.println("\nidcard.cardNo = " + idCard.getCardNo()); System.out.println("idcard.person.name = " + idCard.getPerson().getName()); session.getTransaction().commit(); } catch (Exception e) { e.printStackTrace(); session.getTransaction().rollback(); } finally { HibernateUtils.closeSession(session); } } }
运行测试类的各个方法,看下Console里面的变化
运行了save1方法后的结果是:
Hibernate: insert into t_idcard (cardNo) values (?) Hibernate: insert into t_person (name, id) values (?, ?)
然后又运行了load方法:
Hibernate: select person0_.id as id1_0_, person0_.name as name1_0_ from t_person person0_ where person0_.id=? person.name=刘德华 Hibernate: select idcard0_.id as id0_1_, idcard0_.cardNo as cardNo0_1_, person1_.id as id1_0_, person1_.name as name1_0_ from t_idcard idcard0_ left outer join t_person person1_ on idcard0_.id=person1_.id where idcard0_.id=? idcard.cardNo234589389894893384
再运行了load2方法:
Hibernate: select idcard0_.id as id0_1_, idcard0_.cardNo as cardNo0_1_, person1_.id as id1_0_, person1_.name as name1_0_ from t_idcard idcard0_ left outer join t_person person1_ on idcard0_.id=person1_.id where idcard0_.id=? idcard.cardNo = 234589389894893384 idcard.person.name = 刘德华
看下数据库: