Hibernate 、多表关联映射 - 一对一关系映射(one- to-one)
hibernate.cfg.xml:
<hibernate-configuration> <session-factory name="sessionFactory"> <property name="hibernate.dialect">org.hibernate.dialect.MySQLDialect</property> <property name="hibernate.connection.driver_class">com.mysql.jdbc.Driver</property> <property name="hibernate.connection.url">jdbc:mysql://localhost:3306/spring?useUnicode=true&characterEncoding=UTF-8</property> <property name="hibernate.connection.username">root</property> <property name="hibernate.connection.password"></property> <property name="hibernate.show_sql">true</property> <property name="hibernate.format_sql">true</property> <property name="hibernate.hbm2ddl.auto">update</property> <mapping resource="cn/hbm/Person.hbm.xml" /> <mapping resource="cn/hbm/IdCard.hbm.xml" /> </session-factory> </hibernate-configuration>
Person:
public class Person { private Integer id; private String name; 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; } }
hbm.xml
<hibernate-mapping package="cn.model"> <class name="Person" table="PERSON"> <id name="id" column="ID"> <generator class="native"></generator> </id> <property name="name" column="NAME" type="java.lang.String" /> <one-to-one name="idCard" /> </class> </hibernate-mapping>
IdCard:
public class IdCard { private Integer id; private Date usefullLife; private Person person; public Person getPerson() { return person; } public void setPerson(Person person) { this.person = person; } public Integer getId() { return id; } public void setId(Integer id) { this.id = id; } public Date getUsefullLife() { return usefullLife; } public void setUsefullLife(Date usefullLife) { this.usefullLife = usefullLife; } }hbm.xml:
<hibernate-mapping package="cn.model"> <class name="IdCard" table="ID_CARD"> <id name="id" column="ID"> <!-- 对一主键关联映射的内容 foreign:表明当前表的主键的生成使用另外一个相关联的对象的标识符(依托于其他表的主键) 和 one-to-one联合一起使用 --> <generator class="foreign"> <param name="property">person</param> </generator> </id> <property name="usefullLife" column="USEFULL_LIFE"/> <!-- constrained="true" 是否添加约束 --> <one-to-one name="person" constrained="true" /> </class> </hibernate-mapping>
创建表并添加数据
public void save(){ Session session=null; Transaction tran=null; try{ Person person=new Person(); person.setName("杰克"); IdCard idCard=new IdCard(); idCard.setUsefullLife(new Date()); idCard.setPerson(person); person.setIdCard(idCard); session=HibernateSessionFactory.getSession(); tran=session.beginTransaction(); session.save(person); session.save(idCard); tran.commit(); }catch(Exception e){ if(session!=null){ session.close(); } } }
执行后会看到,Person和IdCard的id是一样的,通过<generator class="foreign"> 外部关系的型式可以使idCard的id和person的id关联起来
再看一下创建的SQL:
他们关联的关系是使用了主外键约束进行关联;
查询的时候通过Person可以得到IdCard,通过IdCard也可以得到Person
public Person getPersonById(Integer id){ Session session=null; try{ session=HibernateSessionFactory.getSession(); return (Person)session.get(Person.class, id); }catch(Exception e){ if(session!=null){ session.close(); } } return null; } public IdCard getIdCardById(Integer id){ Session session=null; try{ session=HibernateSessionFactory.getSession(); return (IdCard)session.get(IdCard.class, id); }catch(Exception e){ if(session!=null){ session.close(); } } return null; }测试代码:
@Test public void testGet(){ Demo demo=new Demo(); Person per=demo.getPersonById(1); System.out.println("人员姓名:"+per.getName()+",身份证有效期:"+per.getIdCard().getUsefullLife()); }
@Test public void testGet2(){ Demo demo=new Demo(); IdCard idCard=demo.getIdCardById(1); System.out.println("身份证ID:"+idCard.getId()+",人员姓名 :"+idCard.getPerson().getName()); }
通过两个查询可以看出,通过IdCard获取 person的时候,实际上他们是查了两次!
对于这种一对一的映射关系,我们同样可以使用many-to-one的方式进行实现;
只需要在IdCard的映射关系中,使Person唯一即可:
只需要更改IdCard的映射文件即可:
<hibernate-mapping package="cn.model"> <class name="IdCard" table="ID_CARD"> <id name="id" column="ID"> <generator class="native" /> </id> <property name="usefullLife" column="USEFULL_LIFE"/> <many-to-one name="person" column="PERSON_ID" unique="true" not-null="true" /> </class> </hibernate-mapping>
使用这种方式在创建表的时候,表之间关系和one-to-one是一样的:
但是表结构是不一样的,在IdCard表中多了一个外键的关联: