基于外键映射的1-1关联
对于基于外键的1-1关联,其外键可以存放在任意一边,在需要存放外键一端,增加many-to-one元素,为many-to-one元素增加unique=”true” 属性来表示为1-1关联
<many-to-one name=”manager” class=”Manager” column=”manager_id”
cascade=”all” unique=”true”/>
另一端需要使用one-to-one元素,该元素使用property-ref属性指定使用被关联实体主键以外的字段作为关联字段
<one-to-one name=”dept” class=”department” property-ref=”manager”/>
不使用property-ref属性的sql:
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_, department1_.mgr_id as mgr_id3_0_0_ from managers manager0_ left outer join departments department1_ on manager0_.mgr_id=department1_.dept_id where manager0_.mgr_id=?
使用property-ref属性的sql:
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_, department1_.mgr_id as mgr_id3_0_0_ from managers manager0_ left outer join departments department1_ on manager0_.mgr_id=department1_.mgr_id where manager0_.mgr_id=?
public class Department {
private Integer deptId;
private String deptName;
private Manager mgr;
public Integer getDeptId() {
return deptId;
}
public void setDeptId(Integer deptId) {
this.deptId = deptId;
}
public String getDeptName() {
return deptName;
}
public void setDeptName(String deptName) {
this.deptName = deptName;
}
public Manager getMgr() {
return mgr;
}
public void setMgr(Manager mgr) {
this.mgr = mgr;
}
}
package com.atguigu.hibernate.one2one.foreign;
public class Manager {
private Integer mgrId;
private String mgrName;
private Department dept;
public Integer getMgrId() {
return mgrId;
}
public void setMgrId(Integer mgrId) {
this.mgrId = mgrId;
}
public String getMgrName() {
return mgrName;
}
public void setMgrName(String mgrName) {
this.mgrName = mgrName;
}
public Department getDept() {
return dept;
}
public void setDept(Department dept) {
this.dept = dept;
}
}
<?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="native"></generator>
</id>
<property name="deptName" type="string">
<column name="dept_name"></column>
</property>
<!-- 存放外键的一端 使用many-to-one 的方式来映射1-1关联关系 -->
<many-to-one name="mgr" class="Manager" column="mgr_id" unique="true">
</many-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 元素,该元素使用property-ref 属性
指定使用被关联实体主键以外的字段作为关联字段,如果没有设置property-ref 的话通过没有外键的一端
来访问关联对象的时候是使用关联对象的主键进行关联的,结果是错误的(应该使用关联实体的外键进行关联)
-->
<one-to-one name="dept" class="Department"
property-ref="mgr"></one-to-one>
</class>
</hibernate-mapping>
<?xml version='1.0' encoding='UTF-8'?>
<!DOCTYPE hibernate-configuration PUBLIC
"-//Hibernate/Hibernate Configuration DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-configuration-3.0.dtd">
<hibernate-configuration>
<session-factory>
<property name="dialect">org.hibernate.dialect.MySQLDialect</property>
<property name="connection.url">jdbc:mysql://localhost:3306/cms</property>
<property name="connection.username">root</property>
<property name="connection.password">123</property>
<property name="connection.driver_class">com.mysql.jdbc.Driver</property>
<property name="myeclipse.connection.profile">example</property>
<property name="hibernate.c3p0.max_size">20</property>
<property name="hibernate.c3p0.min_size">5</property>
<property name="hibernate.c3p0.timeout">5000</property>
<property name="hibernate.c3p0.max_statements">100</property>
<property name="hibernate.c3p0.idle_test_period">3000</property>
<property name="hibernate.c3p0.acquire_increment">2</property>
<property name="hbm2ddl.auto">update</property>
<property name="show_sql">true</property>
<property name="sql_format">true</property>
<mapping resource="com/atguigu/hibernate/one2one/foreign/Manager.hbm.xml"/>
<mapping resource="com/atguigu/hibernate/one2one/foreign/Department.hbm.xml"/>
</session-factory>
</hibernate-configuration>
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);
//保存操作
//建议先保存没有外键列的那个对象,这样会减少update语句
session.save(manager);
session.save(department);
}
@Test
public void testGet(){
//1.默认情况下对关联属性使用懒加载
//2.所以会出现懒加载异常的问题
Department dept = (Department) session.get(Department.class, 1);
System.out.println(dept.getDeptName());
// session.close();
// Manager mgr = dept.getMgr();
// System.out.println(mgr.getClass());
//打印上面的输出语句只是输出mgr的类的类型,不会初始化延迟加载的对象
//当访问对象的属性的时候才会查询晚加载的对象。
//System.out.println(mgr.getMgrName());
//3.查询Manager 对象的链接条件应该是dept.manager_id = mgr.manager_id
//而不应该是dept.dept_id = mgr.manager_id
Manager mgr = dept.getMgr();
System.out.println(mgr.getMgrName());
}
public void testGet2(){
//在查询没有外键的实体对象时,使用的是左外链接查询,一并查询出其关联的对象
//并已经进行初始化。没有延迟加载的问题出现
Manager mgr = (Manager) session.get(Manager.class, 1);
System.out.println(mgr.getMgrName());
System.out.println(mgr.getDept().getDeptName());
}
}