基于主键映射的1-1

基于主键的映射策略:指一端的主键生成器使用foreign策略,表明根据”对方”的主键来生成自己的主键,自己并不能独立生成主键。<param>子元素指定使用当前持久化类的哪个

属性的主键作为”对方“

<id name=”id” column=”id” type=”integer”>

         <generator class=”foreign”>

                   <param name=”property”>mgr</param>

         </generator>

</id>

 

采用foreign主键生成器策略的一端增加one-to-one元素映射关联属性,其one-to-one属性

还应增加constrained=”true” 属性,设置外键约束 ;另一端增加one-to-one 元素映射关联属性。

Constrained(约束):指定为当前持久化类对应的数据库表的主键增加一个外键约束,引用被关联的对象(”对方“)所对应的数据表主键

       <!--

           采用foreign 主键生成器策略的一端增加one-to-one 元素映射关联属性,

           其one-to-one 节点还应增加constrained=true属性,以使当前的主键上增加外键约束。

        -->

       <one-to-one name="mgr" class="Manager" constrained="true"></one-to-one>

 

而在主键生成策略不是foreign的一端其<one-to-one>中不能设置property-ref属性了

 

实例:

<?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 package="com.atguigu.hibernate.one2one.foreign">

    <class name="Department" table="departments">

       <id name="deptId" type="integer">

           <column name="dept_id"></column>

           <!-- 使用外键的方式来生成当前的主键 -->

           <generator class="foreign">

              <!-- property 属性指定使用当前持久化类的哪一个属性的主键作为外键 -->

              <param name="property">mgr</param>

           </generator>

       </id>

       <property name="deptName" type="string">

           <column name="dept_name"></column>

       </property>

       <!--

           采用foreign 主键生成器策略的一端增加one-to-one 元素映射关联属性,

           其one-to-one 节点还应增加constrained=true属性,以使当前的主键上增加外键约束。

        -->

       <one-to-one name="mgr" class="Manager" constrained="true"></one-to-one>

    </class>

</hibernate-mapping>

 

 

 

<?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 package="com.atguigu.hibernate.one2one.foreign">

    <class name="Manager" table="managers">

       <id name="mgrId" type="integer">

           <column name="mgr_id"></column>

           <generator class="native"></generator>

       </id>

       <property name="mgrName" type="string">

           <column name="mgr_name"></column>

       </property>  

       <!-- 映射1-1的关联关系: 在对应的数据表中已经有外键了,当前持久化类使用

           one-to-one 来进行映射

        -->

 

       <one-to-one name="dept" class="Department"></one-to-one>

 

    </class>

</hibernate-mapping>

 

 

 

 

 

package com.atguigu.hibernate.one2one.foreign;

 

import org.hibernate.Session;

import org.hibernate.SessionFactory;

import org.hibernate.Transaction;

import org.hibernate.cfg.Configuration;

import org.hibernate.service.ServiceRegistry;

import org.hibernate.service.ServiceRegistryBuilder;

import org.junit.After;

import org.junit.Before;

import org.junit.Test;

 

public class HibernateTest01 {

        

         private SessionFactory sessionFactory;

         private Session session;

         private Transaction transaction;

        

         @Before

         public void init(){

                   Configuration conf = new Configuration().configure();

                   ServiceRegistry serviceRegistry = new ServiceRegistryBuilder().applySettings(conf.getProperties()).buildServiceRegistry();

                   sessionFactory = conf.buildSessionFactory(serviceRegistry);

                   session = sessionFactory.openSession();

                   transaction = session.beginTransaction();

         }

         @After

         public void destroy(){

                   transaction.commit();

                   session.close();

                   sessionFactory.close();

         }

         @Test

         public void testSave(){

                   Department department = new Department();

                   department.setDeptName("DEPT-AA");

                  

                   Manager manager = new Manager();

                   manager.setMgrName("MGR-AA");

                  

                   //设定关联关系

                   department.setMgr(manager);

                   manager.setDept(department);

                  

                   //保存操作

                   //主键关联的保存操作是没有先后顺序的,因为在主键生成策略的foreign端,

                   //他的主键必须是非空且唯一的,所以必须要自主生成主键的实体类插入以后,其才能

                   //引用他的主键插入,所以先写哪一个都不会有多余的update

                   session.save(manager);

                   session.save(department);

                  

         }

         @Test

         public void testGet(){

                   //1.默认情况下对关联属性使用懒加载

                   //2.所以会出现懒加载异常的问题

                  

                   Department dept = (Department) session.get(Department.class, 1);//如果只查department同样会有懒加载

                   System.out.println(dept.getDeptName());

                   //如果加上manager之后会查询manager的时候会输出左外链接的语句,因为manager表中没有外键 ,

                   //不知道其关联的deptartment是谁 ,所以查询的时候会连同其关联的department一同查询出来。

                   Manager mgr = dept.getMgr();

                   System.out.println(mgr.getMgrName());

         }

         @Test

         public void testGet2(){

                   //在查询没有外键的实体对象时,使用的是左外链接查询,一并查询出其关联的对象

                   //并已经进行初始化

                   Manager mgr = (Manager) session.get(Manager.class, 1);

                   System.out.println(mgr.getMgrName());

                   System.out.println(mgr.getDept().getDeptName());

                   //生成主键的一端不能再使用property-ref属性了,如果使用了就不对了

                   //Hibernate: select manager0_.mgr_id as mgr_id1_1_1_, manager0_.mgr_name as mgr_name2_1_1_, department1_.dept_id as dept_id1_0_0_, department1_.dept_name as dept_nam2_0_0_ from managers manager0_ left outer join departments department1_ on manager0_.mgr_id=department1_.dept_id where manager0_.mgr_id=?

         }

}