MyBatis(三)(1)

简介: MyBatis(三)(1)

6. 自定义映射resultMap

6.1 代码结构

SqlSessionUtils.java、jdbc.properties、log4j.xml延用上面章节的。

6.1.1 mybatis-config.xml

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE configuration
        PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
        "http://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration>
    <properties resource="jdbc.properties"/>
    <!--设置MyBatis的全局配置-->
    <settings>
        <!--将_自动映射为驼峰,emp_name:empName-->
        <setting name="mapUnderscoreToCamelCase" value="true"/>
        <!--开启延迟加载-->
        <setting name="lazyLoadingEnabled" value="true"/>
    </settings>
    <typeAliases>
        <package name="com.atguigu.mybatis.pojo"/>
    </typeAliases>
    <environments default="development">
        <environment id="development">
            <transactionManager type="JDBC"/>
            <dataSource type="POOLED">
                <property name="driver" value="${jdbc.driver}"/>
                <property name="url" value="${jdbc.url}"/>
                <property name="username" value="${jdbc.username}"/>
                <property name="password" value="${jdbc.password}"/>
            </dataSource>
        </environment>
    </environments>
    <mappers>
        <package name="com.atguigu.mybatis.mapper"/>
    </mappers>
</configuration>

6.1.2 pojo

Dept

部门信息

package com.atguigu.mybatis.pojo;
public class Dept {
    private Integer did;
    private String deptName;
    //省略get、set
}
Emp

员工信息

package com.atguigu.mybatis.pojo;
public class Emp {
    private Integer eid;
    private String empName;
    private Integer age;
    private String sex;
    private String email;
    //员工所属部门
    private Dept dept;
}

6.1.3 mapper

EmpMapper
package com.atguigu.mybatis.mapper;
import com.atguigu.mybatis.pojo.Emp;
public interface EmpMapper {
    /**
     * 查询所有的员工信息
     */
    List<Emp> getAllEmp();
    /**
     * 查询员工以及员工所对应的部门信息
     */
    Emp getEmpAndDept(@Param("eid") Integer eid);
    /**
     * 通过分步查询查询员工以及员工所对应的部门信息
     * 分步查询第一步:查询员工信息
     */
    Emp getEmpAndDeptByStepOne(@Param("eid") Integer eid);
    /**
     * 通过分步查询查询部门以及部门中所有的员工信息
     * 分步查询第二步:根据did查询员工信息
     */
    List<Emp> getDeptAndEmpByStepTwo(@Param("did") Integer did);
}
DeptMapper
package com.atguigu.mybatis.mapper;
import com.atguigu.mybatis.pojo.Dept;
public interface DeptMapper {
    /**
     * 通过分步查询查询员工以及员工所对应的部门信息
     * 分步查询第二步:通过did查询员工所对应的部门
     */
    Dept getEmpAndDeptByStepTwo(@Param("did") Integer did);
    /**
     * 获取部门以及部门中所有的员工信息
     */
    Dept getDeptAndEmp(@Param("did") Integer did);
    /**
     * 通过分步查询查询部门以及部门中所有的员工信息
     * 分步查询第一步:查询部门信息
     */
    Dept getDeptAndEmpByStepOne(@Param("did") Integer did);
}

6.2 映射文件和测试编写

EmpMapper.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.atguigu.mybatis.mapper.EmpMapper">
    <!--
        resultMap:设置自定义映射关系
        id:唯一标识,不能重复
        type:设置映射关系中的实体类类型
        子标签:
        id:设置主键的映射关系
        result:设置普通字段的映射关系
        属性:
        property:设置映射关系中的属性名,必须是type属性所设置的实体类类型中的属性名
        column:设置映射关系中的字段名,必须是sql语句查询出的字段名
    -->
    <resultMap id="empResultMap" type="Emp">
        <id property="eid" column="eid"></id>
        <result property="empName" column="emp_name"></result>
        <result property="age" column="age"></result>
        <result property="sex" column="sex"></result>
        <result property="email" column="email"></result>
    </resultMap>
    <!--List<Emp> getAllEmp();-->
    <select id="getAllEmp" resultMap="empResultMap">
        select * from t_emp
    </select>
    <!--处理多对一映射关系方式一:级联属性赋值-->
    <resultMap id="empAndDeptResultMapOne" type="Emp">
        <id property="eid" column="eid"></id>
        <result property="empName" column="emp_name"></result>
        <result property="age" column="age"></result>
        <result property="sex" column="sex"></result>
        <result property="email" column="email"></result>
        <result property="dept.did" column="did"></result>
        <result property="dept.deptName" column="dept_name"></result>
    </resultMap>
    <!--处理多对一映射关系方式二:association-->
    <resultMap id="empAndDeptResultMapTwo" type="Emp">
        <id property="eid" column="eid"></id>
        <result property="empName" column="emp_name"></result>
        <result property="age" column="age"></result>
        <result property="sex" column="sex"></result>
        <result property="email" column="email"></result>
        <!--
            association:处理多对一的映射关系
            property:需要处理多对的映射关系的属性名
            javaType:该属性的类型
        -->
        <association property="dept" javaType="Dept">
            <id property="did" column="did"></id>
            <result property="deptName" column="dept_name"></result>
        </association>
    </resultMap>
    <!--Emp getEmpAndDept(@Param("eid") Integer eid);-->
    <select id="getEmpAndDept" resultMap="empAndDeptResultMapTwo">
        select * from t_emp left join t_dept on t_emp.did = t_dept .did where t_emp.eid = #{eid}
    </select>
    <resultMap id="empAndDeptByStepResultMap" type="Emp">
        <id property="eid" column="eid"></id>
        <result property="empName" column="emp_name"></result>
        <result property="age" column="age"></result>
        <result property="sex" column="sex"></result>
        <result property="email" column="email"></result>
        <!--
            select:设置分步查询的sql的唯一标识(namespace.SQLId或mapper接口的全类名.方法名)
            column:设置分布查询的条件
            fetchType:当开启了全局的延迟加载之后,可通过此属性手动控制延迟加载的效果
            fetchType="lazy|eager":lazy表示延迟加载,eager表示立即加载
        -->
        <association property="dept"
                     select="com.atguigu.mybatis.mapper.DeptMapper.getEmpAndDeptByStepTwo"
                     column="did"
                     fetchType="eager"></association>
    </resultMap>
    <!--Emp getEmpAndDeptByStepOne(@Param("eid") Integer eid);-->
    <select id="getEmpAndDeptByStepOne" resultMap="empAndDeptByStepResultMap">
        select * from t_emp where eid = #{eid}
    </select>
    <select id="getAllEmpOld" resultType="Emp">
        <!--select eid,emp_name empName,age,sex,email from t_emp-->
        select * from t_emp
    </select>
    <!--List<Emp> getDeptAndEmpByStepTwo(@Param("did") Integer did);-->
    <select id="getDeptAndEmpByStepTwo" resultType="Emp">
        select * from t_emp where did = #{did}
    </select>
</mapper>

ResultMapTest.java

package com.atguigu.mybatis.test;
import com.atguigu.mybatis.mapper.DeptMapper;
import com.atguigu.mybatis.mapper.EmpMapper;
import com.atguigu.mybatis.pojo.Dept;
import com.atguigu.mybatis.pojo.Emp;
import com.atguigu.mybatis.utils.SqlSessionUtils;
public class ResultMapTest {
    /**
     * 解决字段名和属性名不一致的情况:
     * a>为字段起别名,保持和属性名的一致
     * b>设置全局配置,将_自动映射为驼峰
     * <setting name="mapUnderscoreToCamelCase" value="true"/>
     * c>通过resultMap设置自定义的映射关系
     * <resultMap id="empResultMap" type="Emp">
     *     <id property="eid" column="eid"></id>
     *     <result property="empName" column="emp_name"></result>
     *     <result property="age" column="age"></result>
     *     <result property="sex" column="sex"></result>
     *     <result property="email" column="email"></result>
     * </resultMap>
     *
     * 处理多对一的映射关系:
     * a>级联属性赋值
     * b>association
     * c>分步查询
     *
     * 处理一对多的映射关系
     * a>collection
     * b>分步查询
     */
    @Test
    public void testGetEmpAndDeptByStep(){
        SqlSession sqlSession = SqlSessionUtils.getSqlSession();
        EmpMapper mapper = sqlSession.getMapper(EmpMapper.class);
        Emp emp = mapper.getEmpAndDeptByStepOne(3);
        System.out.println(emp.getEmpName());
        System.out.println("+++++++++++++++++++++++++++++++++++++");
        System.out.println(emp.getDept());
    }
    @Test
    public void testGetEmpAndDept(){
        SqlSession sqlSession = SqlSessionUtils.getSqlSession();
        EmpMapper mapper = sqlSession.getMapper(EmpMapper.class);
        Emp emp = mapper.getEmpAndDept(3);
        System.out.println(emp);
    }
    @Test
    public void testGetAllEmp(){
        SqlSession sqlSession = SqlSessionUtils.getSqlSession();
        EmpMapper mapper = sqlSession.getMapper(EmpMapper.class);
        List<Emp> list = mapper.getAllEmp();
        list.forEach(emp -> System.out.println(emp));
    }
    @Test
    public void testGetDeptAndEmp(){
        SqlSession sqlSession = SqlSessionUtils.getSqlSession();
        DeptMapper mapper = sqlSession.getMapper(DeptMapper.class);
        Dept dept = mapper.getDeptAndEmp(1);
        System.out.println(dept);
    }
    @Test
    public void testGetDeptAndEmpByStep(){
        SqlSession sqlSession = SqlSessionUtils.getSqlSession();
        DeptMapper mapper = sqlSession.getMapper(DeptMapper.class);
        Dept dept = mapper.getDeptAndEmpByStepOne(1);
        System.out.println(dept.getDeptName());
    }
}

6.2.1 resultMap处理字段和属性的映射关系

resultMap:设置自定义映射

id:表示自定义映射的唯一标识,不能重复

type:查询的数据要映射的实体类的类型

id:设置主键的映射关系

result:设置普通字段的映射关系

property:设置映射关系中实体类中的属性名

column:设置映射关系中中的字段名

EmpMapper.xml

若字段名和实体类中的属性名不一致,则可以通过resultMap设置自定义映射,即使字段名和属性名一致的属性也要映射,也就是全部属性都要列出来

<!--resultMap:设置自定义映射
id:设置唯一标识,不能重复
type:设置实体类类型
-->
<resultMap id="empResultMap" type="Emp">
  <!--id:设置主键映射关系
    property:设置实体类的属性名
    column:设置表中对应的字段-->
    <id property="eid" column="eid"></id>
  <result property="empName" column="emp_name"></result>
  <result property="age" column="age"></result>
  <result property="sex" column="sex"></result>
  <result property="email" column="email"></result>
</resultMap>
<!--List<Emp> getAllEmp();-->
<select id="getAllEmp" resultMap="empResultMap">
  select * from t_emp
</select>
@Test
  //获取所有的员工
    public void testGetAllEmp(){
        SqlSession sqlSession = SqlSessionUtils.getSqlSession();
        EmpMapper mapper = sqlSession.getMapper(EmpMapper.class);
        List<Emp> list = mapper.getAllEmp();
        list.forEach(emp -> System.out.println(emp));
    }

若字段名和实体类中的属性名不一致,但是字段名符合数据库的规则(使用_),实体类中的属性名符合Java的规则(使用驼峰)。此时也可通过以下两种方式处理字段名和实体类中的属性的映射关系

  1. 可以通过为字段起别名的方式,保证和实体类中的属性名保持一致
<!--List<Emp> getAllEmp();-->
<select id="getAllEmp" resultType="Emp">
  select eid,emp_name empName,age,sex,email from t_emp
</select>
  1. 可以在MyBatis的核心配置文件中的setting标签中,设置一个全局配置信息mapUnderscoreToCamelCase,可以在查询表中数据时,自动将_类型的字段名转换为驼峰,例如:字段名user_name,设置了mapUnderscoreToCamelCase,此时字段名就会转换为userName。
<settings>
 <setting name="mapUnderscoreToCamelCase" value="true"/>
</settings>

6.2.2 多对一映射处理

查询员工信息以及员工所对应的部门信息

public class Emp {  
  private Integer eid;  
  private String empName;  
  private Integer age;  
  private String sex;  
  private String email;  
    
    //加一行这个    员工所属的部门  多个员工对应一个部门
  private Dept dept;
  //...构造器、get、set方法等
}
6.2.2.1 级联方式处理映射关系
<resultMap id="empAndDeptResultMapOne" type="Emp">
  <id property="eid" column="eid"></id>
  <result property="empName" column="emp_name"></result>
  <result property="age" column="age"></result>
  <result property="sex" column="sex"></result>
  <result property="email" column="email"></result>
    
  <result property="dept.did" column="did"></result>
  <result property="dept.deptName" column="dept_name"></result>
</resultMap>
<!--Emp getEmpAndDept(@Param("eid")Integer eid);-->
<select id="getEmpAndDept" resultMap="empAndDeptResultMapOne">
  select * from t_emp left join t_dept on t_emp.eid = t_dept.did where t_emp.eid = #{eid}
</select>
@Test
  //获取员工信息  和这个员工所属的部门
    public void testGetEmpAndDept(){
        SqlSession sqlSession = SqlSessionUtils.getSqlSession();
        EmpMapper mapper = sqlSession.getMapper(EmpMapper.class);
        Emp emp = mapper.getEmpAndDept(3);
        System.out.println(emp);
    }
6.2.2.2 使用association处理映射关系
  • association:处理多对一的映射关系
  • property:需要处理多对的映射关系的属性名
  • javaType:该属性的类型
<resultMap id="empAndDeptResultMapTwo" type="Emp">
  <id property="eid" column="eid"></id>
  <result property="empName" column="emp_name"></result>
  <result property="age" column="age"></result>
  <result property="sex" column="sex"></result>
  <result property="email" column="email"></result>
  
    <association property="dept" javaType="Dept">
    <id property="did" column="did"></id>
    <result property="deptName" column="dept_name"></result>
  </association>
</resultMap>
<!--Emp getEmpAndDept(@Param("eid")Integer eid);-->
<select id="getEmpAndDept" resultMap="empAndDeptResultMapTwo">
  select * from t_emp left join t_dept on t_emp.eid = t_dept.did where t_emp.eid = #{eid}
</select>
6.2.2.3 分步查询

1. 查询员工信息

  • select:设置分布查询的sql的唯一标识(namespace.SQLId或mapper接口的全类名.方法名)
  • column:设置分步查询的条件
//EmpMapper里的方法
/**
 * 通过分步查询,员工及所对应的部门信息
 * 分步查询第一步:查询员工信息
 * @param  
 * @return com.atguigu.mybatis.pojo.Emp
 */
Emp getEmpAndDeptByStepOne(@Param("eid") Integer eid);
<resultMap id="empAndDeptByStepResultMap" type="Emp">
  <id property="eid" column="eid"></id>
  <result property="empName" column="emp_name"></result>
  <result property="age" column="age"></result>
  <result property="sex" column="sex"></result>
  <result property="email" column="email"></result>
    
    <!--
        select:设置分步查询的sql的唯一标识(namespace.SQLId或mapper接口的全类名.方法名)
        column:设置分布查询的条件
        fetchType:当开启了全局的延迟加载之后,可通过此属性手动控制延迟加载的效果
        fetchType="lazy|eager":lazy表示延迟加载,eager表示立即加载
    --> 
    <association property="dept"
         select="com.atguigu.mybatis.mapper.DeptMapper.getEmpAndDeptByStepTwo"
         column="did"></association>
</resultMap>
<!--Emp getEmpAndDeptByStepOne(@Param("eid") Integer eid);-->
<select id="getEmpAndDeptByStepOne" resultMap="empAndDeptByStepResultMap">
  select * from t_emp where eid = #{eid}
</select>

2. 查询部门信息

//DeptMapper里的方法
/**
 * 通过分步查询,员工及所对应的部门信息
 * 分步查询第二步:通过did查询员工对应的部门信息
 * @param
 * @return com.atguigu.mybatis.pojo.Emp
 */
Dept getEmpAndDeptByStepTwo(@Param("did") Integer did);
<!--此处的resultMap仅是处理字段和属性的映射关系-->
<resultMap id="EmpAndDeptByStepTwoResultMap" type="Dept">
  <id property="did" column="did"></id>
  <result property="deptName" column="dept_name"></result>
</resultMap>
<!--Dept getEmpAndDeptByStepTwo(@Param("did") Integer did);-->
<select id="getEmpAndDeptByStepTwo" resultMap="EmpAndDeptByStepTwoResultMap">
  select * from t_dept where did = #{did}
</select>

MyBatis(三)(2)+https://developer.aliyun.com/article/1556671

目录
相关文章
|
1月前
|
SQL 安全 Java
MyBatis(6)#{}和${}的区别
在MyBatis中,`#{}`和`${}`是用于在SQL语句中嵌入参数的两种方式。`#{}`用于预处理参数,可以防止SQL注入;而`${}`进行直接字符串替换,适用于动态插入表名或列名,但存在SQL注入风险。建议优先使用`#{}`,并在必要时谨慎使用`${}`。
|
4月前
|
SQL Java 数据库连接
在mybatis中#{}和${}的区别
在MyBatis中,使用#{}可以防止SQL注入,它通过预处理语句来安全地设置参数值,而${}会将传入的数据直接插入SQL语句中,不安全,通常用于传入数据库对象或在确保数据安全的情况下使用。
|
5月前
|
SQL 存储 Java
MyBatis(三)(2)
MyBatis(三)(2)
20 1
|
5月前
|
SQL 缓存 Java
MyBatis(三)(3)
MyBatis(三)(3)
20 1
|
5月前
|
SQL Java 数据库连接
MyBatis(二)(2)
MyBatis(二)(2)
19 0
|
5月前
|
SQL Java 数据库连接
MyBatis(二)(1)
MyBatis(二)(1)
19 0
|
SQL XML Java
MyBatis配置中的#「」和$「」有什么区别?
Mybatis提供到的#号和$号,都是实现动态SQL的一种方式,通过这两种方式把参数传递到XML之后,在执行操作之前,Mybatis会对这两种占位符进行动态解析。
128 0
|
7月前
|
Java 数据库连接 测试技术
一文彻底搞懂Mybatis系列(八)之Mybatis参数处理
一文彻底搞懂Mybatis系列(八)之Mybatis参数处理
707 0
|
SQL 存储 缓存
mybatis中#{}和${}的区别
mybatis中#{}和${}的区别
197 0
mybatis中#{}和${}的区别
|
SQL Java 数据库连接
Mybatis中的#与$的区别
Mybatis中的#与$的区别
94 0