MyBatis笔记 | 详解resultType和resultMap

目录

一、resultType

1、select返回List

2、select记录封装Map

3、返回单个实体类的Map

4、返回多个实体类的Map

二、resultMap

1、通过resultMap实现高级结果映射集

2、使用resultMap进行关联查询

3、使用级联属性封装结果来进行关联查询

4、使用association定义关联对象封装规则

5、使用association进行分步查询

6、使用collection定义关联的集合类型元素的封装规则

7、使用collection定义关联的集合元素分步查询

8、使用discriminator鉴别器


一、resultType

从这条语句中返回的期望类型的类的完全限定名或别名,注意如果是集合,那应该是集合可以包含的类型,而不能是集合本身。
下面我们来讨论其返回List和Map的情况:

1、select返回List

在select元素中,如果返回的是一个集合,要在sql映射中写集合中元素的类型。

我们想实现通过名字来进行模糊查询,返回Employee类型的List集合。

public List<Employee> getEmpsByLastNameLike(String lastName);

然后我们在sql映射文件中配置如下:

<select id="getEmpsByLastNameLike" resultType="com.cerr.mybatis.Employee">
        select * from tb1_employee where last_name like #{lastName}
</select>

注意resultType填入的是Employee的类型而不是List类型。

测试方法,查询名字带有e的:

package com.cerr.mybatis;
import com.cerr.mybatis.dao.EmployeeMapper;
import com.cerr.mybatis.dao.EmployeeMapperAnnotation;
import org.apache.ibatis.io.Resources;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;
import org.junit.Test;
import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import static org.junit.Assert.*;
public class MyBatisTest {

    //获取SQLSessionFactory
    public SqlSessionFactory getSqlSessionFactory() throws IOException {
        String resource = "mybatis-config.xml";
        InputStream inputStream = Resources.getResourceAsStream(resource);
        return new SqlSessionFactoryBuilder().build(inputStream);
    }

    @Test
    public void test9() throws IOException {
        //获取SqlSessionFactory
        SqlSessionFactory sqlSessionFactory = getSqlSessionFactory();
        //获取SqlSession
        SqlSession sqlSession = sqlSessionFactory.openSession();
        try {
            //获取接口的实现类对象:会为接口自动的创建一个代理对象,代理对象去执行增删改查
            EmployeeMapper employeeMapper = sqlSession.getMapper(EmployeeMapper.class);

            //调用方法
            List<Employee> list = employeeMapper.getEmpsByLastNameLike("%e%");
            for (Employee employee : list){
                System.out.println(employee);
            }

        }finally {
            //关闭
            sqlSession.close();
        }
    }
}

结果:

 
13424350-328f8e186678575c.png
 

2、select记录封装Map

有两种情况,一种是返回单个实体类的Map;另一种是返回多个实体类的Map。

3、返回单个实体类的Map

如果返回的是单个实体类的Map,那么在select元素中的resultType的值就是map

我们想返回的Map是key为记录的列名,值为记录的值。我们首先在接口中定义一个方法:

public Map<String,Object> getEmpByIdReturnMap(Integer id);

然后在sql映射文件中给予配置,注意resultType的值是map

package com.cerr.mybatis;

import com.cerr.mybatis.dao.EmployeeMapper;
import com.cerr.mybatis.dao.EmployeeMapperAnnotation;
import org.apache.ibatis.io.Resources;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;
import org.junit.Test;

import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import static org.junit.Assert.*;

public class MyBatisTest {

    //获取SQLSessionFactory
    public SqlSessionFactory getSqlSessionFactory() throws IOException {
        String resource = "mybatis-config.xml";
        InputStream inputStream = Resources.getResourceAsStream(resource);
        return new SqlSessionFactoryBuilder().build(inputStream);
    }

    @Test
    public void test8() throws IOException {
        //获取SqlSessionFactory
        SqlSessionFactory sqlSessionFactory = getSqlSessionFactory();
        //获取SqlSession
        SqlSession sqlSession = sqlSessionFactory.openSession();
        try {
            //获取接口的实现类对象:会为接口自动的创建一个代理对象,代理对象去执行增删改查
            EmployeeMapper employeeMapper = sqlSession.getMapper(EmployeeMapper.class);
            Map<String,Object> map = employeeMapper.getEmpByIdReturnMap(1);
            System.out.println(map);
        }finally {
            //关闭
            sqlSession.close();
        }
    }
}

4、返回多个实体类的Map

我们想返回多个实体类的Map的话,那么resultType的值应该是实体类,而不是map本身。

我们想返回多个Employee组成的Map,key为Employee中的id顺序,在这里我们需要使用到@MapKey注解来指明我们要封装哪个属性为Map的key,值是Employee对象,我们先在接口中定义方法:

    //告诉MyBatis封装这个Map的时候使用哪个属性作为Map的key
    @MapKey("id")
    public Map<Integer,Employee> getEmpByLastNameReturnMap(String lastName);

SQL 映射文件:

    <select id="getEmpByLastNameReturnMap" resultType="com.cerr.mybatis.Employee">
        select * from tb1_employee where last_name like #{lastName}
    </select>

测试方法:

public class MyBatisTest {

    //获取SQLSessionFactory
    public SqlSessionFactory getSqlSessionFactory() throws IOException {
        String resource = "mybatis-config.xml";
        InputStream inputStream = Resources.getResourceAsStream(resource);
        return new SqlSessionFactoryBuilder().build(inputStream);
    }

    @Test
    public void test9() throws IOException {
        //获取SqlSessionFactory
        SqlSessionFactory sqlSessionFactory = getSqlSessionFactory();
        //获取SqlSession
        SqlSession sqlSession = sqlSessionFactory.openSession();
        try {
            //获取接口的实现类对象:会为接口自动的创建一个代理对象,代理对象去执行增删改查
            EmployeeMapper employeeMapper = sqlSession.getMapper(EmployeeMapper.class);

            Map<Integer,Employee> map = employeeMapper.getEmpByLastNameReturnMap("%e%");
            System.out.println(map);
        }finally {
            //关闭
            sqlSession.close();
        }
    }
}

结果:

 
13424350-8450543c4d9ec890.png
 

二、resultMap

1、通过resultMap实现高级结果映射集

其属性如下:

  • type:自定义规则的Java类型
  • id:唯一id方便引用
<mapper namespace="com.cerr.mybatis.dao.EmployeeMapperPlus">
    <!-- 定义封装规则 -->
    <resultMap id="myEmp" type="com.cerr.mybatis.Employee">
        <id column="id" property="id"/>
        <result column="last_name" property="lastName"/>
        <result column="email" property="email"/>
        <result column="gender" property="gender"/>
    </resultMap>
    <select id="getEmpById" resultMap="myEmp">
        select * from tb1_employee where id = #{id}
    </select>
</mapper>

上述代码中,<id>子标签指定主键列的封装规则。

  • column:指定哪一列
  • property:指定对应的JavaBean属性

<result>子标签定义普通列的封装规则,属性与<id>的属性用法一致。对于主键来说也可以使用<result>定义规则,但是使用<id>定义主键会有底层优化,所以我们推荐主键使用<id>标签来定义

定义好规则后,<resultMap>idmyEmp,这个id可供下面的<select>标签引用,即resultMap="myEmp"

测试方法如下:

package com.cerr.mybatis;
import com.cerr.mybatis.dao.EmployeeMapper;
import com.cerr.mybatis.dao.EmployeeMapperAnnotation;
import com.cerr.mybatis.dao.EmployeeMapperPlus;
import org.apache.ibatis.io.Resources;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;
import org.junit.Test;
import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import static org.junit.Assert.*;
public class MyBatisTest {
    //获取SQLSessionFactory
    public SqlSessionFactory getSqlSessionFactory() throws IOException {
        String resource = "mybatis-config.xml";
        InputStream inputStream = Resources.getResourceAsStream(resource);
        return new SqlSessionFactoryBuilder().build(inputStream);
    }
    @Test
    public void test10() throws IOException {
        //获取SqlSessionFactory
        SqlSessionFactory sqlSessionFactory = getSqlSessionFactory();
        //获取SqlSession
        SqlSession sqlSession = sqlSessionFactory.openSession();
        try {
            //获取接口的实现类对象:会为接口自动的创建一个代理对象,代理对象去执行增删改查
            EmployeeMapperPlus mapper = sqlSession.getMapper(EmployeeMapperPlus.class);
            Employee employee = mapper.getEmpById(1);
            System.out.println(employee);
        }finally {
            //关闭
            sqlSession.close();
        }
    }

2、使用resultMap进行关联查询

首先我们定义一个Department类并且新建一张表:

/**新建表**/
create table tbl_dept(
    id int(11) primary key auto_increment,
    dept_name varchar(255)
)
/**对tb1_employee表新增一列**/
alter table tb1_employee add column d_id int(11);
/**新增外键**/
alter table tb1_employee add constraint fk_emp_dept foreign key(d_id) 
    references tbl_dept(id);
package com.cerr.mybatis;
public class Department {
    private Integer id;
    private String departmentName;
    public Integer getId() {
        return id;
    }
    public void setId(Integer id) {
        this.id = id;
    }
    public String getDepartmentName() {
        return departmentName;
    }
    public void setDepartmentName(String departmentName) {
        this.departmentName = departmentName;
    }
    @Override
    public String toString() {
        return "Department{" +
                "id=" + id +
                ", departmentName='" + departmentName + '\'' +
                '}';
    }
}

3、使用级联属性封装结果来进行关联查询

EmployeeMapperPlus接口中新增一个方法:

public Employee getEmpAndDept(Integer id);

SQL映射文件配置如下,在resultMap中使用department.id这种级联写法来封装结果集:

    <resultMap id="myDifEmp" type="com.cerr.mybatis.Employee">
        <id column="id" property="id"/>
        <result column="last_name" property="lastName"/>
        <result column="gender" property="gender"/>
        <result column="did" property="department.id"/>
        <result column="dept_name" property="department.departmentName"/>
    </resultMap>
    <select id="getEmpAndDept" resultMap="myDifEmp">
        select e.id id ,e.last_name last_name ,e.gender gender ,e.email email,d.id did,d.dept_name dept_name from
         tb1_employee e,tbl_dept d where e.d_id=d.id and e.id = #{id}
    </select>

4、使用association定义关联对象封装规则

我们也可以使用<association><association>可以指定联合的JavaBean对象,其中的property属性指定哪个属性是联合的对象,javaType属性指定这个属性对象的类型。
示例如下:

    <resultMap id="myDifEmp2" type="com.cerr.mybatis.Employee">
        <id column="id" property="id"/>
        <result column="last_name" property="lastName"/>
        <result column="gender" property="gender"/>
 
        <association property="department" javaType="com.cerr.mybatis.Department">
            <id column="did" property="id"/>
            <result column="dept_name" property="departmentName"/>
        </association>
    </resultMap>
    <select id="getEmpAndDept" resultMap="myDifEmp2">
        select e.id id ,e.last_name last_name ,e.gender gender ,e.email email,d.id did,d.dept_name dept_name from
         tb1_employee e,tbl_dept d where e.d_id=d.id and e.id = #{id}
    </select>

5、使用association进行分步查询

对于上面的关联对象查询中,我们可以将其分解为两步,其SQL如下:

select * from tb1_employee where id = ?
select id,dept_name departmentName from tbl_dept where id = ?

即先通过id在tb1_employee表中查出信息,并且该记录中有一个d_id字段,我们将该字段作为第二条sql语句的参数去tbl_dept表中查出记录,并把该记录封装成Department,然后赋值给Employeedepartment属性。此时就可以用到我们的分步查询。

EmployeeMapper接口中新增一个方法:

public Employee getEmpByIdStep(Integer id);

我们新建一个DepartmentMapper接口:

package com.cerr.mybatis.dao;

import com.cerr.mybatis.Department;

public interface DepartmentMapper {

    public Department getDeptById(Integer id);
}

然后新建一个SQL映射文件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.cerr.mybatis.dao.DepartmentMapper">
    <!--
        1.先按照员工id查询员工信息
        2.根据查询员工信息中的d_id去部门表查出部门信息
        3.部门设置到员工中
    -->
    <resultMap id="myEmpByStep" type="com.cerr.mybatis.Employee">
        <id column="id" property="id"/>
        <result column="last_name" property="lastName"/>
        <result column="gender" property="gender"/>
        <result column="email" property="email"/>
        <!--
            流程:使用select指定的方法(传入column指定的这列参数的值)查出对象,并封装给property指定的属性
        -->
        <association property="department"
                     select="com.cerr.mybatis.dao.DepartmentMapper.getDeptById"
                     column="d_id">
        </association>
    </resultMap>
    <select id="getEmpByIdStep" resultMap="myEmpByStep">
        select * from tb1_employee where id = #{id}
    </select>
</mapper>

上述配置使用了association标签来配置分步查询的方法,select属性表明当前属性是调用select指定的方法查出的结果,要填入该方法的完整名字(包括全类名)。column属性指定将哪一列的值传给这个方法。

测试方法:

package com.cerr.mybatis;
import com.cerr.mybatis.dao.EmployeeMapper;
import com.cerr.mybatis.dao.EmployeeMapperAnnotation;
import com.cerr.mybatis.dao.EmployeeMapperPlus;
import org.apache.ibatis.io.Resources;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;
import org.junit.Test;
import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import static org.junit.Assert.*;
public class MyBatisTest {

    //获取SQLSessionFactory
    public SqlSessionFactory getSqlSessionFactory() throws IOException {
        String resource = "mybatis-config.xml";
        InputStream inputStream = Resources.getResourceAsStream(resource);
        return new SqlSessionFactoryBuilder().build(inputStream);
    }
    @Test
    public void test12() throws IOException {
        SqlSessionFactory sqlSessionFactory = getSqlSessionFactory();
        SqlSession sqlSession = sqlSessionFactory.openSession();
        try {
            EmployeeMapperPlus mapper = sqlSession.getMapper(EmployeeMapperPlus.class);
            Employee employee = mapper.getEmpByIdStep(1);
            System.out.println(employee);
            System.out.println(employee.getDepartment());
        }finally {
            //关闭
            sqlSession.close();
        }
    }
}

结果如下:

 
13424350-b1cddee64ff6215b.png
 

延迟加载

我们上述方法查询的时候,每次查询Employee对象的时候,都将Department一起查询出来了,而我们想将部门信息等到我们要使用的时候再去查询。只需要在上述的分步查询的基础上在全局配置文件中配置lazyLoadingEnabledaggressiveLazyLoading即可。

    <settings>
        <setting name="lazyLoadingEnabled" value="true"/>
        <setting name="aggressiveLazyLoading" value="false"/>
    </settings>

我们修改上面分步查询中的测试方法,不使用到department字段:

    @Test
    public void test12() throws IOException {
        SqlSessionFactory sqlSessionFactory = getSqlSessionFactory();
        SqlSession sqlSession = sqlSessionFactory.openSession();
        try {
            EmployeeMapperPlus mapper = sqlSession.getMapper(EmployeeMapperPlus.class);
            Employee employee = mapper.getEmpByIdStep(1);
            System.out.println(employee.getEmail());
        }finally {
            //关闭
            sqlSession.close();
        }
    }

在控制台中看其SQL的信息(此处使用了log4j,详情看这篇文章:MyBatis | 使用log4j在控制台输出SQL语句):
没有查询Department表:

 
13424350-c54a2ff08ef81612.png
 


若需要使用到department字段时:

@Test
    public void test12() throws IOException {
        SqlSessionFactory sqlSessionFactory = getSqlSessionFactory();
        SqlSession sqlSession = sqlSessionFactory.openSession();
        try {
            EmployeeMapperPlus mapper = sqlSession.getMapper(EmployeeMapperPlus.class);
            Employee employee = mapper.getEmpByIdStep(1);
            System.out.println(employee.getEmail());
            System.out.println(employee.getDepartment());
        }finally {
            //关闭
            sqlSession.close();
        }
    }
 
13424350-fa6d93766ee93caa.png
 

6、使用collection定义关联的集合类型元素的封装规则

例如我们案例中,对于一个Department类中,嵌套了一个Employee类型的集合,那么我们想在查询Department的时候顺便将其集合元素查询出来,我们就可以通过使用collection嵌套结果集的方式,定义关联的集合类型元素的封装规则。

collection标签:定义关联集合类型的属性的封装规则,其有两个比较重要的属性:

  • property:定义关联集合类型的属性的封装规则
  • ofType:指定集合里面元素的类型

我们先在Department类中加入集合元素

private List<Employee> emps;

再加入对应的getter/setter,还有重写toString()

    public List < Employee > getEmps() {
        return emps;
    }

    public void setEmps(List < Employee > emps) {
        this.emps = emps;
    }
    @Override
    public String toString() {
        return "Department{" +
                "id=" + id +
                ", departmentName='" + departmentName + '\'' +
                ", emps=" + emps +
                '}';
    }

DepartmentMapper接口中新增方法:

public Department getDeptByIdPlus(Integer id);

SQL映射文件配置:

<resultMap id="myDept" type="com.cerr.mybatis.Department">
        <id column="did" property="id"/>
        <result column="dept_name" property="departmentName"/>
        <!-- 员工 : 集合类型-->
        <collection property="emps" ofType="com.cerr.mybatis.Employee">
            <!-- 定义元素的封装规则 -->
            <id column="eid" property="id"/>
            <result column="last_name" property="lastName"/>
            <result column="email" property="email"/>
            <result column="gender" property="gender"/>
        </collection>
    </resultMap>
    <select id="getDeptByIdPlus" resultMap="myDept">
        select d.id did,d.dept_name dept_name,e.id eid,e.last_name last_name
                ,e.email email,e.gender gender
        from tbl_dept d
        left join tb1_employee e
        on d.id = e.d_id
        where d.id = #{id}
    </select>

测试方法:

package com.cerr.mybatis;
import com.cerr.mybatis.dao.DepartmentMapper;
import com.cerr.mybatis.dao.EmployeeMapper;
import com.cerr.mybatis.dao.EmployeeMapperAnnotation;
import com.cerr.mybatis.dao.EmployeeMapperPlus;
import org.apache.ibatis.io.Resources;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;
import org.junit.Test;
import java.io.IOException;
import java.io.InputStream;
import java.util.HashMap;
import java.util.Map;
public class MyBatisTest {

    //获取SQLSessionFactory
    public SqlSessionFactory getSqlSessionFactory() throws IOException {
        String resource = "mybatis-config.xml";
        InputStream inputStream = Resources.getResourceAsStream(resource);
        return new SqlSessionFactoryBuilder().build(inputStream);
    }

    @Test
    public void test13() throws IOException {
        SqlSessionFactory factory = getSqlSessionFactory();
        SqlSession session = factory.openSession();
        try{
            DepartmentMapper mapper = session.getMapper(DepartmentMapper.class);
            Department department = mapper.getDeptByIdPlus(1);
            System.out.println(department);
            System.out.println(department.getEmps());
        }finally {
            session.close();
        }
    }
}

结果:

 
13424350-8b3ac7ffcc2efae6.png
 

7、使用collection定义关联的集合元素分步查询

这个与association进行分步查询的结果类似,只是association是针对单个元素,而collection针对集合元素。
对于上面使用collection定义关联的集合类型元素的封装规则中的代码中,我们可以拆分为:

select * from tbl_dept where id = ?;
select * from tb1_employee where d_id = ?;

既先查tbl_dept表中的记录,然后根据Departmentid字段的记录去tb1_employee表中查询符合条件的Employee记录,并封装成集合然后给Department包装。

EmployeeMapperPlus接口方法:

public List<Employee> getEmpsByDeptId(Integer deptId);

SQL映射文件EmployeeMapperPlus.xml

    <select id="getEmpsByDeptId" resultType="com.cerr.mybatis.Employee">
        select * from tb1_employee where d_id = #{deptId}
    </select>

DepartmentMapperPlus接口方法:

public Department getDeptByIdStep(Integer id);

SQL映射文件:

    <resultMap id="myDeptStep" type="com.cerr.mybatis.Department">
        <id column="id" property="id"/>
        <result column="dept_name" property="departmentName"/>
        <collection property="emps"
                    select="com.cerr.mybatis.dao.EmployeeMapperPlus.getEmpsByDeptId"
                    column="id"></collection>
    </resultMap>
    <select id="getDeptByIdStep" resultMap="myDeptStep">
        select id,dept_name departmentName from tbl_dept where id = #{id}
    </select>

测试方法:

package com.cerr.mybatis;
import com.cerr.mybatis.dao.DepartmentMapper;
import com.cerr.mybatis.dao.EmployeeMapper;
import com.cerr.mybatis.dao.EmployeeMapperAnnotation;
import com.cerr.mybatis.dao.EmployeeMapperPlus;
import org.apache.ibatis.io.Resources;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;
import org.junit.Test;
import java.io.IOException;
import java.io.InputStream;
import java.util.HashMap;
import java.util.Map;
public class MyBatisTest {

    //获取SQLSessionFactory
    public SqlSessionFactory getSqlSessionFactory() throws IOException {
        String resource = "mybatis-config.xml";
        InputStream inputStream = Resources.getResourceAsStream(resource);
        return new SqlSessionFactoryBuilder().build(inputStream);
    }

    @Test
    public void test13() throws IOException {
        SqlSessionFactory factory = getSqlSessionFactory();
        SqlSession session = factory.openSession();
        try{
            DepartmentMapper mapper = session.getMapper(DepartmentMapper.class);
            Department department = mapper.getDeptByIdStep(1);
            System.out.println(department);
            System.out.println(department.getEmps());
        }finally {
            session.close();
        }
    }
}

结果:

 
13424350-375af7d9f7d73790.png
 

collection的扩展

对于分步查询传递多列值的时候,可以将其值封装成map再传递进column属性。其格式如{key1=column1,key2=column2,...}
对于上面的配置文件,我们可以修改为column="{deptId=id}",具体配置如下:

    <resultMap id="myDeptStep" type="com.cerr.mybatis.Department">
        <id column="id" property="id"/>
        <result column="dept_name" property="departmentName"/>
        <collection property="emps"
                    select="com.cerr.mybatis.dao.EmployeeMapperPlus.getEmpsByDeptId"
                    column="{deptId=id}" fetchType="lazy"></collection>
    </resultMap>
    <select id="getDeptByIdStep" resultMap="myDeptStep">
        select id,dept_name departmentName from tbl_dept where id = #{id}
    </select>

collection中有一个fetchType属性,其有两种取值:

  • lazy:表示使用延迟加载
  • eager:表示使用立即加载

8、使用discriminator鉴别器

MyBatis可以使用discriminator判断某列的值,然后根据某列的值改变其封装行为。

对于discriminator标签,有如下两个属性

  • column:指定判定的列名
  • javaType:指定列值对应的java类型

discriminator标签还有一个子标签case,其属性如下:

  • value:列的值
  • resultType:指定封装的结果类型

现在我们有一个要求,如果在查询Employee时,查出的是女生,就把部门信息查询出来,否则就不查询;如果是男生,就把last_name这一列的值赋值给email
这样的话,我们首先要使用<resultMap>标签进行自定义结果集封装,对于其他的列值,我们就依旧使用<id><result >标签来封装,对于gender属性我们使用<discriminator >来判定,SQL映射文件如下:

    <resultMap id="myEmpDis" type="com.cerr.mybatis.Employee">
        <id column="id" property="id"/>
        <result column="last_name" property="lastName"/>
        <result column="gender" property="gender"/>
        <result column="email" property="email"/>
        <discriminator javaType="java.lang.String" column="gender">
            <!-- 女生 resultType:指定封装的结果类型 -->
            <case value="0" resultType="com.cerr.mybatis.Employee">
                <association property="department"
                             select="com.cerr.mybatis.dao.DepartmentMapper.getDeptById"
                             column="d_id">
                </association>
            </case>
            <!-- 男生 -->
            <case value="1" resultType="com.cerr.mybatis.Employee">
                <id column="id" property="id"/>
                <result column="last_name" property="lastName"/>
                <result column="gender" property="gender"/>
                <result column="last_name" property="email"/>
            </case>
        </discriminator>
    <select id="getEmpByIdStep" resultMap="myEmpDis">
        select * from tb1_employee where id = #{id}
    </select>

测试方法:

package com.cerr.mybatis;
import com.cerr.mybatis.dao.DepartmentMapper;
import com.cerr.mybatis.dao.EmployeeMapper;
import com.cerr.mybatis.dao.EmployeeMapperAnnotation;
import com.cerr.mybatis.dao.EmployeeMapperPlus;
import org.apache.ibatis.io.Resources;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;
import org.junit.Test;
import java.io.IOException;
import java.io.InputStream;
import java.util.HashMap;
import java.util.Map;
public class MyBatisTest {

    //获取SQLSessionFactory
    public SqlSessionFactory getSqlSessionFactory() throws IOException {
        String resource = "mybatis-config.xml";
        InputStream inputStream = Resources.getResourceAsStream(resource);
        return new SqlSessionFactoryBuilder().build(inputStream);
    }

    @Test
    public void test12() throws IOException {
        SqlSessionFactory sqlSessionFactory = getSqlSessionFactory();
        SqlSession sqlSession = sqlSessionFactory.openSession();
        try {
            EmployeeMapperPlus mapper = sqlSession.getMapper(EmployeeMapperPlus.class);
            Employee employee = mapper.getEmpByIdStep(4);
            System.out.println(employee);
            System.out.println(employee.getDepartment());
        }finally {
            //关闭
            sqlSession.close();
        }
    }
}

上述代码中,id=4的Employee是女生,因此会查询Department:

 
13424350-4034bbdb0e90b1fc.png
 


我们将传入的id值改为1(男生),所以不会查询Department,所以获取其department值的时候是null,并且email的值与其lastName的值一样:

 
13424350-10926dc296ea531a.png
 

猜你喜欢

转载自blog.csdn.net/qq_14810195/article/details/103307133