MyBatis
高级映射/关联查询:
- 一对一/多对一
- 一对多
- 多对多
主要使用的是resultMap的 collection属性 和 association属性的使用
association
association:用于映射关联查询到单个对象的信息,将关联查询信息映射到一个pojo对象中,多用于一对一/多对一的场景。
collection
collection:对关联查询到的多条记录映射到集合中,一般就是将关联查询信息映射到一个list集合中,用于一对多/多对多的场景。
关联查询
一个简单的例子,部门和员工的映射
部门:Dept.java
public class Dept {
private Integer id ; // 部门编号
private String name ; // 部门名称
private String address ; // 部门地址
// 部门里的员工
private List<Employee> employees ;
数据库:
create table DEMO_MAWEI_DEPT
(
D_ID NUMBER not null,
D_NAME VARCHAR2(50) not null,
D_ADDRESS VARCHAR2(100)
)
数据:
员工:Employee.java
public class Employee {
private int id ; // 员工号
private String name; // 员工姓名
private Dept dept ; // 所在部门
private String address ; // 家庭地址
// 所拥有的电脑
private List<Computer> computers ;
数据库:
create table DEMO_MAWEI_EMPLOYEE
(
E_ID NUMBER not null,
E_NAME VARCHAR2(50) not null,
D_ID NUMBER not null,
E_ADDRESS VARCHAR2(100)
)
数据:
电脑:Computer.java
public class Computer {
private Integer id ; // 电脑编号
private String name ; // 电脑名称
private Double money ; // 电脑价值
// 使用者
private Employee employee;
数据库:
create table DEMO_MAWEI_COMPUTER
(
C_ID NUMBER not null,
C_NAME VARCHAR2(50),
C_MONEY NUMBER(10,2),
E_ID NUMBER
)
数据:
其中有一些setting和getting没有写,可以自行补上,及MAVEN配置和mybatis的配置可以在前文中看见。
浅谈MyBatis 之 入门(一)
一对一/多对一
就以:员工和部门之间的映射,一个员工对应一个部门(多个员工对应一个部门)
Employee.xml
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.wm.mybatis.dao.IEmployeeMapperDao">
<resultMap type="Employee" id="employeeMap">
<id property="id" column="e_id"/>
<result property="name" column="e_name"/>
<result property="address" column="e_address"/>
<!-- 一对一/多对一:
association:用于映射关联查询单个对象的信息
property属性: 是Employee类中的属性对应
resultMap属性: 是 可以对应Employee类中的属性Dept类映射文件中的一个结果集映射
命名空间+resultMap的id
-->
<association property="dept" resultMap="com.wm.mybatis.dao.IDeptMapperDao.resultDept" />
</resultMap>
<!-- 通过id获取员工信息 -->
<select id="getEmployeeById" parameterType="int" resultMap="employeeMap">
<![CDATA[
select *
from base_55demo.demo_mawei_employee t inner join
base_55demo.demo_mawei_dept d
on d.d_id = t.d_id
and t.e_id = #{id}
]]>
</select>
</mapper>
其中resultMap :association:用于映射关联查询单个对象的信息
<association property="dept" resultMap="com.wm.mybatis.dao.IDeptMapperDao.resultDept" />
它是关联的一个已经存在的一个resultMap。=命名空间+resultMap的ID。
也可以有另一种写法:
<!-- 另一种写法 -->
<resultMap type="Employee" id="employeeMap2">
<id property="id" column="e_id"/>
<result property="name" column="e_name"/>
<result property="address" column="e_address"/>
<association property="dept" javaType="Dept" >
<id property="id" column="d_id" />
<result property="name" column="d_name" />
<result property="address" column="d_address" />
</association>
</resultMap>
测试:
public class EmployeeMapperDaoImpl implements IEmployeeMapperDao{
@Override
public Employee getEmployeeById(int id) {
Employee employee = null ;
try {
SqlSession session = SessionManagerUtil.getSession();
employee = (Employee)session.selectOne(IEmployeeMapperDao.class.getName()+".getEmployeeById", id);
} catch (Exception e) {
e.printStackTrace();
} finally {
SessionManagerUtil.closeSession();
}
return employee;
}
}
结果:
public class TestEmployeeMapper {
@Test
public void getEmployeeById(){
EmployeeMapperDaoImpl dao = new EmployeeMapperDaoImpl();
Employee employee = dao.getEmployeeById(1001);
System.out.println(employee);
}
}
一对多
部门与员工的映射:一个部门中有多个员工。
Dept.xml
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.wm.mybatis.dao.IDeptMapperDao">
<resultMap type="Dept" id="resultDeptMap">
<result property="id" column="d_id" />
<result property="name" column="d_name" />
<result property="address" column="d_address" />
<!-- 一对多 List 列表
collection:对关联查询到的多条记录映射到集合中
property:employees为Dept类中的对应的属性
-->
<collection property="employees" ofType="com.wm.mybatis.POJO.Employee" column="d_id" >
<id property="id" column="e_id" javaType="int" jdbcType="INTEGER"/>
<result property="name" column="e_name" javaType="string" jdbcType="VARCHAR"/>
<result property="address" column="e_address" javaType="string" jdbcType="VARCHAR"/>
<result property="d_id" column="d_id" javaType="int" jdbcType="INTEGER"/>
</collection>
</resultMap>
<!-- 最基本的Dept结果集映射 -->
<resultMap type="Dept" id="resultDept">
<id property="id" column="d_id" />
<result property="name" column="d_name" />
<result property="address" column="d_address" />
</resultMap>
<select id="findDeptById" parameterType="int" resultMap="resultDeptMap">
<![CDATA[
select d.*,e.*
from demo_mawei_dept d,
demo_mawei_employee e
where d.d_id = e.d_id
and d.d_id = #{id}
]]>
</select>
</mapper>
其中resultMap :collection:对关联查询到的多条记录映射到list集合中。
其实其中collection可以简写成一个已有的映射结果集。
<!-- 另一种写法 -->
<resultMap type="Dept" id="resultDeptMap2">
<id property="id" column="d_id"/>
<result property="name" column="d_name"/>
<result property="address" column="d_address"/>
<!--
property:对应的Dept类中的属性
resultMap:对应的Employee的一个最简单的一个结果集映射 = 命名空间+resultMap的ID
-->
<collection property="employees" resultMap="com.wm.mybatis.dao.IEmployeeMapperDao.basicEmployee" />
</resultMap>
而Employee.xml中:对应的最基本的结果集映射:
(com.wm.mybatis.dao.IEmployeeMapperDao.basicEmployee)
<!-- 最基本的Employee结果集 -->
<resultMap type="Employee" id="basicEmployee">
<id property="id" column="e_id"/>
<result property="name" column="e_name"/>
<result property="address" column="e_address"/>
</resultMap>
测试:
public class DeptMapperDaoImpl implements IDeptMapperDao{
@Override
public Dept findDeptById(int id) {
Dept dept = null ;
try {
SqlSession session = SessionManagerUtil.getSession();
dept = session.selectOne(IDeptMapperDao.class.getName()+".findDeptById", id) ;
} catch (Exception e) {
e.printStackTrace();
} finally{
SessionManagerUtil.closeSession();
}
return dept;
}
}
结果:
public class TestDeptMapper {
@Test
public void findDeptById(){
IDeptMapperDao dao = new DeptMapperDaoImpl();
Dept dept = dao.findDeptById(1);
System.out.println(dept);
}
}
多对多
就以:部门里有多个员工,每一个员工又有多台电脑。
Dept.xml
<select id="getDeptByIdWithComputer" parameterType="int" resultMap="deptMore2More2">
<![CDATA[
select *
from base_55demo.demo_mawei_dept d,
base_55demo.demo_mawei_employee e,
base_55demo.demo_mawei_computer c
where d.d_id = e.d_id
and e.e_id = c.e_id
and d.d_id = #{id}
]]>
</select>
<!-- 多对多 -->
<resultMap type="Dept" id="deptMore2More2">
<id property="id" column="d_id"/>
<result property="name" column="d_name"/>
<result property="address" column="d_address"/>
<!-- 部门 与 员工 property:Dept类的属性 ofType:对应的类型(配置了别名的) -->
<collection property="employees" ofType="Employee">
<id property="id" column="e_id"/>
<result property="name" column="e_name"/>
<result property="address" column="e_address"/>
<!-- 员工 与 电脑 property:Computer类的属性 ofType:对应的类型(配置了别名的)-->
<collection property="computers" ofType="Computer">
<id property="id" column="c_id"/>
<result property="name" column="c_name"/>
<result property="money" column="c_money"/>
</collection>
</collection>
</resultMap>
其中:resultMap采用了嵌套 collection 实现的。
但是也可以引用已有的结果集:
resultMap 简化:
<!-- 另一种写法 -->
<resultMap type="Dept" id="deptMore2More">
<id property="id" column="d_id"/>
<result property="name" column="d_name"/>
<result property="address" column="d_address"/>
<!-- 已有的结果集映射 部门和员工的映射 -->
<collection property="employees" resultMap="com.wm.mybatis.dao.IEmployeeMapperDao.employeeWithComputer" />
</resultMap>
部门和员工的映射:
(com.wm.mybatis.dao.IEmployeeMapperDao.employeeWithComputer)
<!-- 连带电脑拥有者 -->
<resultMap type="Employee" id="employeeWithComputer">
<id property="id" column="e_id"/>
<result property="name" column="e_name"/>
<result property="address" column="e_address"/>
<!-- 已有的结果集映射 员工 和 电脑的映射 -->
<collection property="computers" resultMap="com.wm.mybatis.dao.IComputerMapperDao.basicComputer" />
</resultMap>
员工 和 电脑的映射:
(com.wm.mybatis.dao.IComputerMapperDao.basicComputer)
Computer.xml:
<mapper namespace="com.wm.mybatis.dao.IComputerMapperDao">
<resultMap type="Computer" id="basicComputer">
<id property="id" column="c_id"/>
<result property="name" column="c_name"/>
<result property="money" column="c_money"/>
</resultMap>
</mapper>
测试:
DeptMapperDaoImpl.java
@Override
public Dept getDeptByIdWithComputer(int id) {
Dept dept = null ;
try {
SqlSession session = SessionManagerUtil.getSession();
dept = session.selectOne(IDeptMapperDao.class.getName()+".getDeptByIdWithComputer", id) ;
} catch (Exception e) {
e.printStackTrace();
} finally{
SessionManagerUtil.closeSession();
}
return dept;
}
结果:
@Test
public void getDeptByIdWithComputer(){
IDeptMapperDao dao = new DeptMapperDaoImpl();
Dept dept = dao.getDeptByIdWithComputer(19);
System.out.println(dept);
}
高级映射:关联查询基本上都是对 resultMap 的标签:collection 和 association 的一些嵌套使用。