在Hibernate查询中存在一对多,多对一,多对多、一对一关系,本篇就简单的对一对一查询进行总结,
一对一关联查询有两种方式,一个是基于外键的一个是基于主键的
一、基于外键的
1.sql语句
CREATE TABLE `manger` (
`MGR_ID` int(2) NOT NULL,
`MGR_NAME` varchar(30) DEFAULT NULL,
PRIMARY KEY (`MGR_ID`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
CREATE TABLE `deptment` (
`DEPT_ID` int(2) NOT NULL AUTO_INCREMENT,
`DEPT_NAME` varchar(30) DEFAULT NULL,
`MGR_ID` int(2) DEFAULT NULL,
PRIMARY KEY (`DEPT_ID`),
UNIQUE KEY `mgr_id_sy` (`MGR_ID`) USING BTREE,
CONSTRAINT `mgr_id_fk` FOREIGN KEY (`MGR_ID`) REFERENCES `manger` (`MGR_ID`)
) ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULT CHARSET=utf8;
deptment表有一个关联manger表的外键,并且是唯一的
2.实体和表映射文件
public class Manger implements java.io.Serializable {
private Integer mgrId;
private String mgrName;
private Deptment dept;
}
Manger.hbm.xml
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd">
<!--
Mapping file autogenerated by MyEclipse Persistence Tools
-->
<hibernate-mapping package="com.zhuojing.hibernate.entities.onetoone.foreign">
<class name="Manger" table="manger" catalog="hibernate">
<id name="mgrId" type="java.lang.Integer">
<column name="MGR_ID" />
<generator class="assigned" />
</id>
<property name="mgrName" type="java.lang.String">
<column name="MGR_NAME" length="30" />
</property>
<!-- 映射1 - 1 的关联关系:在对应的数据表中已经有外键了,当持久化类使用 one-to-one 进行映射 -->
<!-- 没有外键的另一端需要使用one-to-one元素,该元素使用 property-ref 属性指定使用被关联实体主键以外的字段作为关联字段 -->
<one-to-one name="dept" class="Deptment" property-ref="manger"></one-to-one>
</class>
</hibernate-mapping>
deptment表实体
public class Deptment implements java.io.Serializable {
private Integer deptId;
private Manger manger;
private String deptName;
}
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd">
<!--
Mapping file autogenerated by MyEclipse Persistence Tools
-->
<hibernate-mapping package="com.zhuojing.hibernate.entities.onetoone.foreign">
<class name="Deptment" table="deptment" catalog="hibernate">
<id name="deptId" type="java.lang.Integer">
<column name="DEPT_ID" />
<generator class="identity" />
</id>
<property name="deptName" type="java.lang.String">
<column name="DEPT_NAME" length="30" />
</property>
<many-to-one name="manger" class="Manger" fetch="select" >
<column name="MGR_ID" unique="true" />
</many-to-one>
</class>
</hibernate-mapping>
3、测试类
import static org.junit.Assert.*;
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;
import com.zhuojing.hibernate.entities.onetomany.Customer;
public class HibernateTest {
private SessionFactory sessionFactory;
private Session session;
private Transaction transaction;
@Before
public void init(){
Configuration configuration = new Configuration().configure();
ServiceRegistry serviceRegistry =
new ServiceRegistryBuilder().applySettings(configuration.getProperties())
.buildServiceRegistry();
sessionFactory = configuration.buildSessionFactory(serviceRegistry);
session = sessionFactory.openSession();
transaction = session.beginTransaction();
}
@After
public void destroy(){
transaction.commit();
session.close();
sessionFactory.close();
}
@Test
public void testSave() {
Deptment deptment = new Deptment();
deptment.setDeptName("DEPT-AA");
//设定关联关系
Manger manger = new Manger(1, "MGR-AA", deptment);
deptment.setManger(manger);
//保存操作
//建议先保存没有带外键列的对象,这样会减少Update
session.save(manger);
session.save(deptment);
}
@Test
public void testGet(){
//默认情况:关联对象会出现懒加载情况
Deptment deptment = (Deptment)session.get(Deptment.class, 1);
System.out.println(deptment.getDeptName());
//2.会出现懒加载异常的问题
System.out.println(deptment.getManger().getMgrName());
//3.查询Manager 对象的连接条件应该是 dept.manager_id = mgr.manager_id
//而不是 dept.dept_id = mgr.manager_id
// Customer customer = (Customer)session.get(Customer.class, 1);
// System.out.println(customer.getCustomerName());
//
// System.out.println(customer.getOrders().iterator().next().getOrderName());
}
@Test
public void testGet2(){
//在查询没有外键的一端的实体对象时:使用的左外键连接查询,一并查询出其关联的对象
//并进行初始化
Manger manger = (Manger)session.get(Manger.class, 1);
System.out.println(manger.getMgrName());
System.out.println(manger.getDept().getDeptName());
}
}
注:
A:插入方法:
a:建议先保存没有带外键列的对象,这样会减少Update
B:查询方法
a:默认情况:关联对象会出现懒加载情况
b:会出现懒加载异常的问题
c:查询Manager 对象的连接条件应该是 dept.manager_id = mgr.manager_id,而不是 dept.dept_id = mgr.manager_id
解决:没有外键的另一端需要使用one-to-one元素,该元素使用 property-ref 属性指定使用被关联实体主键以外的字段作为关联字段(映射文件配置)
二、基于主键的一对一
1、sql语句
CREATE TABLE `manger2` (
`MGR_ID` int(2) NOT NULL,
`MGR_NAME` varchar(30) DEFAULT NULL,
PRIMARY KEY (`MGR_ID`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
CREATE TABLE `deptment2` (
`DEPT_ID` int(2) NOT NULL,
`DEPT_NAME` varchar(30) DEFAULT NULL,
PRIMARY KEY (`DEPT_ID`),
UNIQUE KEY `dept2_id_sy` (`DEPT_ID`) USING BTREE,
CONSTRAINT `dept_id_fk` FOREIGN KEY (`DEPT_ID`) REFERENCES `manger2` (`MGR_ID`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
deptment2 表的主键关联manger2的主键
2.实体和映射文件
public class Manger2 implements java.io.Serializable {
private Integer mgrId;
private String mgrName;
private Deptment2 deptment2;
}
Manger2.hbm.xml
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd">
<!--
Mapping file autogenerated by MyEclipse Persistence Tools
-->
<hibernate-mapping>
<class name="com.zhuojing.hibernate.entities.onetoone.priamy.Manger2" table="manger2" catalog="hibernate">
<id name="mgrId" type="java.lang.Integer">
<column name="MGR_ID" />
<generator class="assigned" />
</id>
<property name="mgrName" type="java.lang.String">
<column name="MGR_NAME" length="30" />
</property>
<one-to-one name="deptment2" class="com.zhuojing.hibernate.entities.onetoone.priamy.Deptment2"></one-to-one>
</class>
</hibernate-mapping>
public class Deptment2 implements java.io.Serializable {
private Integer deptId;
private Manger2 manger;
private String deptName;
}
Deptment2.hbm.xml
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd">
<!--
Mapping file autogenerated by MyEclipse Persistence Tools
-->
<hibernate-mapping>
<class name="com.zhuojing.hibernate.entities.onetoone.priamy.Deptment2" table="deptment2" catalog="hibernate">
<id name="deptId" type="java.lang.Integer">
<column name="DEPT_ID" />
<!-- 使用外键的方式生成当前的主键 -->
<generator class="foreign">
<!-- property 属性使用当前持久化类的哪一个属性的主键作为外键 -->
<param name="property">manger</param>
</generator>
</id>
<property name="deptName" type="java.lang.String">
<column name="DEPT_NAME" length="30" />
</property>
<!--
采用foreign 主键生成器策略的一端增加 one-to-one 元素映射关联属性,
其one-to-one 节点还应增加 constrained=“true” 属性;
以使当前的主键加上外键约束。
-->
<one-to-one name="manger" class="com.zhuojing.hibernate.entities.onetoone.priamy.Manger2" constrained="true"></one-to-one>
</class>
</hibernate-mapping>
测试类
package com.zhuojing.hibernate.entities.onetoone.priamy;
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 HibernateTest {
private SessionFactory sessionFactory;
private Session session;
private Transaction transaction;
@Before
public void init(){
Configuration configuration = new Configuration().configure();
ServiceRegistry serviceRegistry =
new ServiceRegistryBuilder().applySettings(configuration.getProperties())
.buildServiceRegistry();
sessionFactory = configuration.buildSessionFactory(serviceRegistry);
session = sessionFactory.openSession();
transaction = session.beginTransaction();
}
@After
public void destroy(){
transaction.commit();
session.close();
sessionFactory.close();
}
@Test
public void testSave() {
Deptment2 deptment = new Deptment2();
deptment.setDeptName("DEPT-AA");
Manger2 manger = new Manger2(5, "MGR-AA", deptment);
deptment.setManger(manger);
//先插入哪一个都不会出现对于的Update
session.save(manger);
session.save(deptment);
}
@Test
public void testGet(){
//默认情况:关联对象会出现懒加载情况
Deptment2 deptment = (Deptment2)session.get(Deptment2.class, 1);
System.out.println(deptment.getDeptName());
//2.会出现懒加载异常的问题
System.out.println(deptment.getManger().getMgrName());
//3.查询Manager 对象的连接条件应该是 dept.manager_id = mgr.manager_id
//而不是 dept.dept_id = mgr.manager_id
}
@Test
public void testGet2(){
//在查询没有外键的一端的实体对象时:使用的左外键连接查询,一并查询出其关联的对象
//并进行初始化
Manger2 manger = (Manger2)session.get(Manger2.class, 1);
System.out.println(manger.getMgrName());
System.out.println(manger.getDeptment2().getDeptName());
}
}
注:
A:插入方法:
a:先插入哪一个都不会出现多余的Update
B:查询方法
a:在查询没有外键的一端的实体对象时:使用的左外键连接查询,一并查询出其关联的对象,并进行初始化