浅谈MyBatis 之 高级映射/关联查询(四)

MyBatis

高级映射/关联查询:

  • 一对一/多对一
  • 一对多
  • 多对多

主要使用的是resultMapcollection属性 和 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 的一些嵌套使用。

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

天涯共明月

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值