mybatis中的resultMap,结果映射,将返回的数据进行更加高级的自定义规则设置,resultMap

结果映射中还可以使用resultType,它可以指定返回的数据类型,如map



<select id="getEmp" resultType="map">
        select * from emp 
    </select>



映射到map中并不是很好的结果,因为我们不是很清晰的知道map中的数据,所有我们一般指定javabean类型返回,如上面的例子中,查询的emp数据,

我们写一个Emp类来进行参数的封窗。



@Data
public class Emp {
    private Long id;
    private String name;
    private String gender;
    private String email;
}



我们的xml就可以这样写:



<select id="getEmp" resultType="com.mybatis.bean.Emp">
        select id,name,gender,emailfrom emp 
</select>



上面使用resultType的做法,我们可以使用resultMap,实现相同的结果



<!--id  唯一标识-->
    <resultMap id="myEmp" type="com.mybatis.bean.Emp">
            <id column="id" property="id"></id>
            <result column="name" property="name"></result>
            <result column="gender" property="gender"></result>
            <result column="email" property="email"></result>
    </resultMap>

   <select id="getEmp" resultMap="myEmp">
        select id,name,gender,email from emp
    </select>



resultType和resultMap不能同时使用,如果Emp中有一个对象的属性,那么直接使用resultType返回 com.mybatis.bean.Emp将会有问题;

如:Emp中有一个属性dept



@Data
public class Emp {
    private Long id;
    private String name;
    private String gender;
    private String email;
    private Dept dept;



Dept:



@Data
public class Dept {
    private Long deptId;
    private String deptName;



xml:



<select id="getEmpAndDept" resultType="com.mybatis.bean.Emp">
        SELECT e.id,e.name,e.gender,e.email,d.dept_id,d.dept_name  FROM emp e, dept d where e.dept_id = d.dept_id and e.id = #{id}
    </select>



这时候我们发现返回的数据中dept是null,所以这时候我们就可以使用resultMap自定义的映射规则了

第一种方式:



<!--id  唯一标识-->
    <resultMap id="myEmpDept" type="com.mybatis.bean.Emp">
            <id column="id" property="id"></id>
            <result column="name" property="name"></result>
            <result column="gender" property="gender"></result>
            <result column="email" property="email"></result>
            <result column="dept_id" property="dept.deptId"></result>
            <result column="dept_name" property="dept.deptName"></result>
    </resultMap>



第二种方式:使用association



<resultMap id="myEmpDept" type="com.mybatis.bean.Emp">
        <id column="id" property="id"></id>
        <result column="name" property="name"></result>
        <result column="gender" property="gender"></result>
        <result column="email" property="email"></result>
        <!--指定javabean对象,emp的属性dept
        property:指定emp的属性dept
        javaType:指定属性的类型com.mybatis.bean.Dept
        -->
        <association property="dept" javaType="com.mybatis.bean.Dept">
            <id column="dept_id" property="deptId"></id>
            <result column="dept_name" property="deptName"></result>
        </association>
    </resultMap>



SQL这里的resultMap指定上面的id属性



<select id="getEmpAndDept" resultMap="myEmpDept">
        SELECT e.id,e.name,e.gender,e.email,d.dept_id,d.dept_name  FROM emp e, dept d where e.dept_id = d.dept_id and e.id = #{id}
    </select>



这样就可以返回的dept就有数据了。

如果Dept中定义的类型是集合:一个部门对应多个员工



@Data
public class Dept {
    private Long deptId;
    private String deptName;
   private List<Emp> emp;



这时候使用association就不行了,需要使用collection



<resultMap id="myDepts" type="com.mybatis.bean.Dept">
        <id column="dept_id" property="deptId"></id>
        <result column="dept_name" property="deptName"></result>
        <!--property:Dept中的emp属性
                    ofType:集合里面元素的类型
                    -->
        <collection property="emp" ofType="com.mybatis.bean.Emp">
            <id column="id" property="id"></id>
            <result column="name" property="name"></result>
            <result column="gender" property="gender"></result>
            <result column="email" property="email"></result>
        </collection>
    </resultMap>

    <select id="getDept" resultMap="myDepts">
        select d.dept_id,d.dept_name ,e.id,e.name,e.gender,e.email from dept d
        LEFT JOIN emp e ON  d.dept_id = e.dept_id where d.dept_id = #{dept_id}
    </select>



关联的嵌套 Select 查询(分步查询):

同样的需求:查询一个部门中的多个员工

mapper中的接口:



//通过部门的id查询员工
public List<Emp> selectEmps(Integer dept_id);
//通过部门id查询部门
public Dept selectDept(Integer dept_id);



DeptMapper.xml;



<!--分步查询-->
    <resultMap id="myDept" type="com.mybatis.bean.Dept">
        <id column="dept_id" property="deptId"></id>
        <result column="dept_name" property="deptName"></result>
      <!--property:Dept的属性名,column:传入的dept_id,select:查询的语句,fetchType有效值为 lazy 和 eager。 指定属性后,将在映射中忽略全局配置参数 lazyLoadingEnabled,使用属性的值->
        <collection property="emp" column="dept_id"  select="com.mybatis.mapper.EmpMapper.selectEmpsStep"/>
    </resultMap>

    <select id="selectDept" resultMap="myDept">
        SELECT dept_id,dept_name FROM dept WHERE dept_id = #{dept_id}
    </select>



EmpMapper.xml:



<select id="selectEmps" resultType="com.mybatis.bean.Emp">
        SELECT id,name,gender,email FROM emp WHERE dept_id = #{dept_id}
    </select>



mybatis全局配置:



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



最终实现分步查询和延迟加载,当我们访问只dept时,就不会去执行emp的SQL语句



Dept dept = mapper.selectDept(10000);
        System.out.println(dept.getDeptName());
        System.out.println(dept.getEmp());



当我们去访问emp时,就会执行emp的SQL语句。

不过官方说分步查询和延迟加载会有性能问题

mybatis resultMap 官方文档 mybatis resultmap map_java