Hey, Nice to meet You. 

必有过人之节.人情有所不能忍者,匹夫见辱,拔剑而起,挺身而斗,此不足为勇也,天下有大勇者,猝然临之而不惊,无故加之而不怒.此其所挟持者甚大,而其志甚远也.          ☆☆☆所谓豪杰之士,

Mybatis3详解(九)----高级映射之一对多映射

1、案例分析

继续接着上一章来,案例:一个部门可以包含多个员工;Department—>Employee(一对多)。一对多映射用到的resultMap标签中的collection子标签。它的属性和association标签基本一致,可以参考上一章的内容:链接 。下面我们就通过代码来实现一对多映射。

2、嵌套结果

①、分别定义Employee和Department实体类

Employee实体类:(不变,和上一章一样)

Department实体类(加入属性List<Employee> employees用于映射多个员工):

/**
 * 部门实体类
 */
public class Department {
    //部门id
    private Integer deptId;
    //部门名称
    private String deptName;

    //部门有哪些员工
    private List<Employee> employees;

    //getter、setter、toString方法和一些构造方法省略...
}

②、创建DepartmentMapper接口和DepartmentMapper.xml 文件

DepartmentMapper接口:

/**
 * 部门Mapper接口
 */
public interface DepartmentMapper {
    //查询所有数据
    List<Department> selectAll();
    //根据部门id查询数据,这个方法是上一章创建了的
    Department selectDeptByDeptId(@Param("id") Integer deptId);
}

DepartmentMapper.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.thr.mapper.DepartmentMapper">
    <resultMap id="departmentMap" type="com.thr.pojo.Department">
        <id property="deptId" column="department_id"/>
        <result property="deptName" column="department_name"/>
        <!--一对多关联对象,ofType指定的是映射到list集合属性中pojo的类型,也就是尖括号的泛型-->
        <collection property="employees" ofType="employee">
            <id property="empId" column="employee_id"/>
            <result property="empName" column="employee_name"/>
            <result property="empAge" column="employee_age"/>
            <result property="empSex" column="employee_sex"/>
            <result property="empEmail" column="employee_email"/>
            <result property="empAddress" column="employee_address"/>
        </collection>
    </resultMap>

    <!-- 查询所有数据-->
    <select id="selectAll" resultMap="departmentMap">
      SELECT * FROM
      t_employee e,
      t_department d
      WHERE
      e.department_id=d.department_id
    </select>

    <!--根据部门id查询数据-->
    <select id="selectDeptByDeptId" parameterType="int" resultMap="departmentMap">
        SELECT * FROM
        t_employee e,
        t_department d
        WHERE
        e.department_id=d.department_id
        and d.department_id = #{id}
    </select>
</mapper>

③、创建数据库连接文件和日志文件(参考上一章)

④、注册 EmployeeMapper.xml 文件(参考上一章)

⑤、编写测试代码(稍微有一点点改动)

/**
 * 测试代码
 */
public class MybatisTest {
    //定义 SqlSession
    private SqlSession sqlSession = null;
    //定义 DepartmentMapper对象
    private DepartmentMapper mapper = null;

    @Before//在测试方法执行之前执行
    public void getSqlSession(){
        //1、加载 mybatis 全局配置文件
        InputStream is = MybatisTest.class.getClassLoader().getResourceAsStream("mybatis-config.xml");
        //2、创建SqlSessionFactory对象
        SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(is);
        //3、根据 sqlSessionFactory 产生 session
        sqlSession = sqlSessionFactory.openSession();
        //4、创建Mapper接口的的代理对象,getMapper方法底层会通过动态代理生成DepartmentMapper的代理实现类
        mapper = sqlSession.getMapper(DepartmentMapper.class);
    }

    @After//在测试方法执行完成之后执行
    public void destroy() throws IOException {
        sqlSession.commit();
        sqlSession.close();

    }
    //查询所有数据
    @Test
    public void testSelectAll(){
        List<Department> departments = mapper.selectAll();
        for (Department department : departments) {
            System.out.println(department);
        }
    }

    //根据部门id查询数据
    @Test
    public void testSelectEmpByEmpId(){
        Department department = mapper.selectDeptByDeptId(3);
        System.out.println(department);
    }
}

⑥、运行结果

       查询所有数据:

image

通过运行结果可以发现,编号为3和7 部门下分别有多名员工。

根据部门id查询数据:

image

3、分步查询

使用分步查询的好处就是可以设置延迟加载,延迟加载后面会有介绍。

①、更改DepartmentMapper.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.thr.mapper.DepartmentMapper">
    <resultMap id="departmentMap" type="com.thr.pojo.Department">
        <id property="deptId" column="department_id"/>
        <result property="deptName" column="department_name"/>
        <!--一对多关联对象,ofType指定的是映射到list集合属性中pojo的类型,也就是尖括号的泛型
        注意:这里的column属性首先是查询出t_department表的department_id,然后将它以参数的形式传递给select属性
        中的EmployeeMapper.selectEmpByDeptId方法,进而查询出当前部门下的员工-->
        <collection property="employees" ofType="employee" column="department_id"
                    select="com.thr.mapper.EmployeeMapper.selectEmpByDeptId">
        </collection>
    </resultMap>

    <!-- 查询所有数据-->
    <select id="selectAll" resultMap="departmentMap">
      SELECT * FROM t_department
    </select>

    <!--根据部门id查询数据-->
    <select id="selectDeptByDeptId" parameterType="int" resultMap="departmentMap">
        SELECT * FROM t_department WHERE department_id = #{id}
    </select>
</mapper>

特别注意:由于column属性是根据当前t_department表查询出的department_id作为参数,然后通过select属性传递给关联对象的方法,所以我们在查询员工表时,应该根据t_employee表中的字段department_id来查询,而不再是根据employee_id来查询,这一点一定要理解清楚,否则这里无法进行下去。所以我们需要在EmployeeMapper接口中创建一个根据部门id查询员工信息的方法。

 ②、分别在EmployeeMapper接口和EmployeeMapper.xml文件中添加如下代码:

EmployeeMapper接口:

/**
 * 员工Mapper接口
 */
public interface EmployeeMapper {
    //查询所有数据
    List<Employee> selectAll();
    //根据员工id查询数据
    Employee selectEmpByEmpId(@Param("id") Integer empId);

    //据据员工表的department_id查询员工数据,用于一对多的关联查询
    Employee selectEmpByDeptId(@Param("id") Integer deptId);
}

EmployeeMapper.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.thr.mapper.EmployeeMapper">
    <resultMap id="employeeMap" type="com.thr.pojo.Employee">
        <id property="empId" column="employee_id"/>
        <result property="empName" column="employee_name"/>
        <result property="empAge" column="employee_age"/>
        <result property="empSex" column="employee_sex"/>
        <result property="empEmail" column="employee_email"/>
        <result property="empAddress" column="employee_address"/>
        <!-- 一对一关联对象-->
        <!--<association property="department" column="department_id" javaType="department"
                     select="com.thr.mapper.DepartmentMapper.selectDeptByDeptId"/>-->
    </resultMap>
    
    <!-- 查询所有数据-->
    <select id="selectAll" resultMap="employeeMap">
      SELECT * FROM t_employee
    </select>

    <!--根据员工id查询数据-->
    <select id="selectEmpByEmpId" parameterType="int" resultMap="employeeMap">
        SELECT * FROM t_employee where department_id= #{id}
    </select>

    <!--根据员工表的department_id查询员工数据,用于一对多的关联查询-->
    <select id="selectEmpByDeptId" parameterType="int" resultMap="employeeMap">
        SELECT * FROM t_employee where department_id= #{id}
    </select>
</mapper>

这里需要注意的是:要注释掉一方中的关联映射,否则就会导致无限循环映射而导致报错。

③、测试代码

/**
 * 测试代码
 */
public class MybatisTest {
    //定义 SqlSession
    private SqlSession sqlSession = null;
    //定义 DepartmentMapper对象
    private DepartmentMapper mapper = null;

    @Before//在测试方法执行之前执行
    public void getSqlSession(){
        //1、加载 mybatis 全局配置文件
        InputStream is = MybatisTest.class.getClassLoader().getResourceAsStream("mybatis-config.xml");
        //2、创建SqlSessionFactory对象
        SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(is);
        //3、根据 sqlSessionFactory 产生 session
        sqlSession = sqlSessionFactory.openSession();
        //4、创建Mapper接口的的代理对象,getMapper方法底层会通过动态代理生成UserMapper的代理实现类
        mapper = sqlSession.getMapper(DepartmentMapper.class);
    }

    @After//在测试方法执行完成之后执行
    public void destroy() throws IOException {
        sqlSession.commit();
        sqlSession.close();

    }
    //查询所有数据
    @Test
    public void testSelectAll(){
        List<Department> departments = mapper.selectAll();
        for (Department department : departments) {
            System.out.println(department);
        }
    }

    //根据部门id查询数据
    @Test
    public void testSelectDeptByDeptId(){
        Department department = mapper.selectDeptByDeptId(3);
        System.out.println(department);
    }
}

④、运行结果

查询所有数据:

image

根据部门id查询数据:

image

posted @ 2020-11-17 19:04  唐浩荣  阅读(550)  评论(0编辑  收藏  举报