基于主键映射的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=?
}
}