【HIbernate框架学习】:Hibernate对象关系映射之一对一关联映射(一)

来源:互联网 发布:口红与经济数据表格 编辑:程序博客网 时间:2024/05/21 01:52

        一对一关联映射在实际生活中是比较常见的,如人与身份证的关系,通过人这个对象可以找到身份证相关的信

,也可以通过身份证这个对象找到人相关的信息。

       有两种策略可以实现一对一的关联映射:

       主键关联:即让两个对象具有相同的主键值,以表明它们之间的一一对应的关系;数据库表不会有额外的字段来

维护它们之间的关系,仅通过表的主键来关联;

       唯一外键关联:外键关联,本来是用于多对一的配置,但是如果加上唯一的限制之后,也可以用来表示一对一关

联关系。

       

      单向一对一主键关联映射

      我们先来假设一个场景,从Person中能看到IdCard,也就是把idCard数据表中的主键拿过来当做person表的主

键,单向一对一主键关联映射的实现就是它们的主键相等。一对一关联映射是通过在一方(Person)的对象关系配置

文件加入<one-to-one>元素定义的。这里的方向是由Person--->IdCard。

      如下图所示:

      

      下面我们来实现:

       Person实体类:

package com.demo.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;}@Overridepublic String toString() {return "Person [id=" + id + ", name=" + name + ", idCard=" + idCard + "]";}}

       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><class name="com.demo.domain.Person" table="person"><id name="id"><!-- 采用foreign生成策略,forgeign会取得关联对象的标识 --><generator class="foreign"><!-- property只关联对象 --><param name="property">idCard</param></generator></id><property name="name"/><!-- one-to-one指示hibernate如何加载其关联对象,默认根据主键加载也就是拿到关系字段值,根据对端的主键来加载关联对象constrained="true表示,当前主键(person的主键)还是一个外键参照了对端的主键(IdCard的主键),也就是会生成外键约束语句 --><one-to-one name="idCard" constrained="true"/></class></hibernate-mapping>

       IdCard实体类:

package com.demo.domain;public class IdCard {private int id;private String cardNo;public int getId() {return id;}public void setId(int id) {this.id = id;}public String getCardNo() {return cardNo;}public void setCardNo(String cardNo) {this.cardNo = cardNo;}@Overridepublic String toString() {return "IdCard [id=" + id + ", cardNo=" + cardNo + "]";}}

       IdCard对象关系映射配置文件:

<?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><class name="com.demo.domain.IdCard" table="idCard"><id name="id"><generator class="native"/></id><property name="cardNo"/></class></hibernate-mapping>

       测试类代码:

package com.demo.test;import org.hibernate.Session;import com.demo.domain.HibernateUtils;import com.demo.domain.IdCard;import com.demo.domain.Person;import junit.framework.TestCase;/** * 单向一对一关联映射(Person-->IdCard) * @author Administrator * @date 2016年12月8日 */public class One2OneTest extends TestCase {public void testSave1() {Session session = null;try {session = HibernateUtils.getSession();session.beginTransaction();IdCard idCard = new IdCard();idCard.setCardNo("1111111");Person person = new Person();person.setName("张三");//建立单向一对一主键映射关联person.setIdCard(idCard);//没有抛出TransientObjectException//是由一对一关联映射的特性决定的,它必须先保存关联对象IdCard//这样它采用foreign映射策略才能取得关联对象的标识//也就是它默认了cascade属性session.save(person);session.getTransaction().commit();}catch(Exception e) {e.printStackTrace();session.getTransaction().rollback();}finally {HibernateUtils.closeSession(session);}}public void testSave2() {Session session = null;try {session = HibernateUtils.getSession();session.beginTransaction();IdCard idCard = new IdCard();idCard.setCardNo("2222222");Person person = new Person();person.setName("李四");//建立单向一对一主键映射关联person.setIdCard(idCard);//只能将IdCard保存,不能将Person保存//因为关系的维护端在Person端,IdCard不知道Person的存在session.save(idCard);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("person.cardNo=" + person.getIdCard().getCardNo());session.getTransaction().commit();}catch(Exception e) {e.printStackTrace();session.getTransaction().rollback();}finally {HibernateUtils.closeSession(session);}}}

       testSave1()方法:

       控制台输出:

       

       数据库显示:

       

       testSave2()方法:

       控制台输出:

       

       数据库显示:

       

       tesLoad()方法:

       控制台输出:

       

       

       双向一对一主键关联映射

       我们先来假设一个场景,双向一对一主键关联映射与单向一对一主键关联映射的区别就是,单向一对一关联映

射,在person端能看到idCard,而idCard不能看到Person端。而双向一对一关联映射就是在idCard端也能看到

person,也就是不但在Person.hbm.xml中加上<one-to-one>标签,同时在IdCard.hbm.xml文件中加上<one-to-one>标

签。

       如下图所示:

       

       我们来实现:

       Person实体类:同单向一对一主键关联映射的Person实体类一样

       Person对象关系映射配置文件:同单向一对一主键关联映射的Person对象关系映射配置文件一样

       IdCard实体类:

package com.demo.domain;public class IdCard {private int id;private String cardNo;//在一方加入另一方的引用private Person person;public int getId() {return id;}public void setId(int 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;}@Overridepublic String toString() {return "IdCard [id=" + id + ", cardNo=" + cardNo + ", person=" + person + "]";}}

       IdCard对象关系映射配置文件:

<?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><class name="com.demo.domain.IdCard" table="idCard"><id name="id"><generator class="native"/></id><property name="cardNo"/><!-- 一对一关联映射 -->                 <one-to-one name="person" /> </class></hibernate-mapping>

       测试类代码:

package com.demo.test;import org.hibernate.Session;import com.demo.domain.HibernateUtils;import com.demo.domain.IdCard;import com.demo.domain.Person;import junit.framework.TestCase;/** * 双向一对一关联映射(Person<--->IdCard) * @author Administrator * @date 2016年12月8日 */public class One2OneTest extends TestCase {public void testSave1() {Session session = null;try {session = HibernateUtils.getSession();session.beginTransaction();IdCard idCard = new IdCard();idCard.setCardNo("1111111");Person person = new Person();person.setName("张三");//建立一对一关联映射person.setIdCard(idCard);//没有抛出TransientObjectException//是由一对一关联映射的特性决定的,它必须先保存关联对象IdCard//这样它采用foreign映射策略才能取得关联对象的标识//也就是它默认了cascade属性//保存Person对象session.save(person);session.getTransaction().commit();}catch(Exception e) {e.printStackTrace();session.getTransaction().rollback();}finally {HibernateUtils.closeSession(session);}}public void testSave2() {Session session = null;try {session = HibernateUtils.getSession();session.beginTransaction();Person person = new Person();person.setName("李四");IdCard idCard = new IdCard();idCard.setCardNo("2222222");//建立一对一关联映射idCard.setPerson(person);//保存IdCard对象session.save(idCard);//人是不会保存进入数据库的,想要保存需要加:person.setIdCard(idCard);session.getTransaction().commit();}catch(Exception e) {e.printStackTrace();session.getTransaction().rollback();}finally {HibernateUtils.closeSession(session);}}public void testLoad1() {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("person.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("idCard.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);}}}

       testSave1()方法

       控制台输出:

       

       数据库显示:

       

       testSave2()方法

       控制台输出:

       

       数据库显示:

       

       testLoad1()方法

       控制台输出:

       

       testLoad2()方法

       控制台输出:

       

       对于双向一对一主键关联映射一直没想明白,在IdCard对象关系映射文件中的<one-to-one>元素中设置了级联属

性为all,保存idCard对象时候,还是保存不了person对象,不知道原因是什么?待解决



      
1 0
原创粉丝点击