MyBatis学习笔记(八)—— 自定义映射ResultMap

08、自定义映射ResultMap

8.1、解决字段名与属性名的映射关系

在这里插入图片描述

问题:表中的字段名与实体类中的属性名不一致

EmpMapper.java

/**
 * 查询所有员工信息
 */
List<Emp> getAllEmp();

EmpMapper.xml

<!--List<Emp> getAllEmp();-->
<select id="getAllEmp" resultType="emp">
    select * from t_emp
</select>

EmpMapperTest.java

@Test
public void getAllEmp() {
    SqlSession sqlSession = SqlSessionUtils.getSqlSession();
    EmpMapper empMapper = sqlSession.getMapper(EmpMapper.class);
    List<Emp> list = empMapper.getAllEmp();
    list.forEach(emp -> {
        System.out.println(emp);
    });
}

运行结果:

Emp{eid=1, empName=‘null’, age=21, sex=‘男’, email=‘zhangsan@123.com’}
Emp{eid=2, empName=‘null’, age=20, sex=‘女’, email=‘lisi@123.com’}
Emp{eid=3, empName=‘null’, age=24, sex=‘男’, email=‘wangwu@123.com’}
Emp{eid=4, empName=‘null’, age=22, sex=‘男’, email=‘zhaoliu@123.com’}
Emp{eid=5, empName=‘null’, age=25, sex=‘女’, email=‘tianqi@123.com’}

bug:

empName的值均为空

分析:

empName与数据库表中的emp_Name不一致,无法匹配映射。

若字段名和实体类中的属性名不一致,但是字段名符合数据库的规则(使用_),实体类中的属性 名符合Java的规则(使用驼峰)。

解决字段名和属性名不一致的情况:

  • 为字段起别名,保持和属性名的一致
  • 设置全局配置,将_自动映射为驼峰
  • 通过ResultMap设置自定义的映射关系

8.1.1、使用字段别名

为字段起别名,保持和属性名的一致

EmpMapper.xml

<!--List<Emp> getAllEmp();-->
<select id="getAllEmp" resultType="emp">
    select eid,emp_name empName,age,sex,email from t_emp
</select>

运行结果:

Emp{eid=1, empName=‘张三’, age=21, sex=‘男’, email=‘zhangsan@123.com’}
Emp{eid=2, empName=‘李四’, age=20, sex=‘女’, email=‘lisi@123.com’}
Emp{eid=3, empName=‘王五’, age=24, sex=‘男’, email=‘wangwu@123.com’}
Emp{eid=4, empName=‘赵六’, age=22, sex=‘男’, email=‘zhaoliu@123.com’}
Emp{eid=5, empName=‘田七’, age=25, sex=‘女’, email=‘tianqi@123.com’}

8.1.2、使用全局配置mapUnderscoreToCamelCase

  • 可以在MyBatis的核心配置文件中设置一个全局配置信息mapUnderscoreToCamelCase,可 以在查询表中数据时,自动将_类型的字段名转换为驼峰
  • 例如:字段名user_name,设置了mapUnderscoreToCamelCase,此时字段名就会转换为 userName

mybatis_config.xml

<!--设置MyBatis的全局配置-->
<settings>
    <!--将_自动映射为驼峰,emp_name:empName-->
    <setting name="mapUnderscoreToCamelCase" value="true"/>
</settings>

EmpMapper.xml

<!--List<Emp> getAllEmp();-->
<select id="getAllEmp" resultType="emp">
    <!--select eid,emp_name empName,age,sex,email from t_emp-->
    select * from t_emp
</select>

8.1.3、使用ResultMap

若字段名和实体类中的属性名不一致,则可以通过resultMap设置自定义映射

EmpMapper.xml

<!--
    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>

8.2、解决多对一的映射关系

在这里插入图片描述

问题:Emp和Dept为多对一的映射关系

解决多对一的映射关系的情况:

  • 级联属性赋值
  • 使用association
  • 分步查询

8.2.1、级联属性赋值

EmpMapper.xml

<!--处理多对一映射关系方式一:级联属性赋值-->
<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.did = t_dept.did where t_emp.eid = #{eid}
</select>

运行结果:

Emp{eid=1, empName=‘张三’, age=21, sex=‘男’, email=‘zhangsan@123.com’, dept=Dept{did=1, deptName=‘A’}}

8.2.2、使用association

EmpMapper.xml

<!--处理多对一映射关系方式二: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>

8.2.3、分步查询

8.2.3.1、分步查询
  • 第一步:查询员工信息

EmpMapper.java

/**
 * 通过分步查询查询员工以及员工所对应的部门信息
 * 分步查询第一步:查询员工信息
 */
Emp getEmpAndDeptByStepOne(@Param("eid") Integer eid);

EmpMapper.xml

<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:将sql以及查询结果中的某个字段设置为分步查询的条件
    -->
    <association property="dept"
                 select="com.ssm.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>
  • 第二步:通过did查询员工所对应的部门信息

DeptMapper.java

/**
 * 通过分步查询查询员工以及员工所对应的部门信息
 * 分步查询第二步:通过did查询员工所对应的部门信息
 */
Dept getEmpAndDeptByStepTwo(@Param("did") Integer did);

DeptMapper.xml

<!--Dept getEmpAndDeptByStepTwo(@Param("did") Integer did);-->
<select id="getEmpAndDeptByStepTwo" resultType="dept">
    select * from t_dept where did = #{did}
</select>
8.2.3.2、延迟加载

1、分步查询的优点:可以实现延迟加载,但是必须在核心配置文件中设置全局配置信息:

  • lazyLoadingEnabled:延迟加载的全局开关。当开启时,所有关联对象都会延迟加载
  • aggressiveLazyLoading:当开启时,任何方法的调用都会加载该对象的所有属性。 否则,每个属性会按需加载

2、此时就可以实现按需加载,获取的数据是什么,就只会执行相应的sql。此时可通过associationcollection中的fetchType属性设置当前的分步查询是否使用延迟加载,fetchType=“lazy(延迟加载)|eager(立即加载)”

3、代码演示:

(1)配置核心配置文件

mybatis-config.xml

<!--设置MyBatis的全局配置-->
<settings>
    <!--开启延迟加载-->
    <setting name="lazyLoadingEnabled" value="true"/>
</settings>

(2)通过fetchType设置是否开启延迟加载

EmpMapper.xml

<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:将sql以及查询结果中的某个字段设置为分步查询的条件
        fetchType:当开启了全局的延迟加载后,可通过此属性手动控制延迟加载的效果
            fetchType = "lazy|eager"
            lazy:表示延迟加载
            eager:表示立即加载
    -->
    <association property="dept"
                 select="com.ssm.mybatis.mapper.DeptMapper.getEmpAndDeptByStepTwo"
                 column="did"
                 fetchType="eager">
    </association>
</resultMap>

(3)代码测试:

EmpMapperTest.java

@Test
public void getEmpAndDeptByStep() {
    SqlSession sqlSession = SqlSessionUtils.getSqlSession();
    EmpMapper empMapper = sqlSession.getMapper(EmpMapper.class);
    Emp emp = empMapper.getEmpAndDeptByStepOne(1);
    System.out.println(emp.getEmpName());
    System.out.println("-------------------------------");
    System.out.println(emp.getDept());

}

(4)运行结果:

  • 未开启延迟加载

在这里插入图片描述

  • 开启延迟加载

在这里插入图片描述

8.3、解决一对多的映射关系

在这里插入图片描述

问题:Dept和Emp为一对多的映射关系

解决一对多的映射关系的情况:

  • collection
  • 分步查询

8.3.1、collection

DeptMapper.java

/**
 * 获取部门以及部门中所有的员工信息
 */
Dept getDeptAndEmp(@Param("did") Integer did);

DeptMapper.xml

<resultMap id="deptAndEmpResultMap" type="dept">
    <id property="did" column="did"></id>
    <result property="deptName" column="dept_name"></result>
    <!--
        collection:处理一对多的映射关系
        ofType:表示该属性所对应的集合中存储数据的类型
    -->
    <collection property="emps" ofType="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>
    </collection>
</resultMap>
<!--Dept getDeptAndEmp(@Param("did") Integer did);-->
<select id="getDeptAndEmp" resultMap="deptAndEmpResultMap">
    select * from t_dept left join t_emp on t_dept.did = t_emp.did where t_dept.did = #{did}
</select>

8.3.2、分步查询

  • 第一步:查询部门信息

DeptMapper.java

/**
 * 通过分步查询查询部门以及部门中所有的员工信息
 * 分步查询第一步:查询部门信息
 */
Dept getDeptAndEmpByStepOne(@Param("did") Integer did);

DeptMapper.xml

<resultMap id="deptAndEmpByStepResultMap" type="dept">
    <id property="did" column="did"></id>
    <result property="deptName" column="dept_name"></result>
    <collection property="emps"
                select="com.ssm.mybatis.mapper.EmpMapper.getDeptAndEmpByStepTwo"
                column="did"
                ></collection>
</resultMap>

<!--Dept getDeptAndEmpByStepOne(@Param("did") Integer did);-->
<select id="getDeptAndEmpByStepOne" resultMap="deptAndEmpByStepResultMap">
    select * from t_dept where did = #{did}
</select>
  • 根据did查询员工信息

EmpMapper.java

/**
 * 通过分步查询查询部门以及部门中所有的员工信息
 * 分步查询第二步:根据did查询员工信息
 */
List<Emp> getDeptAndEmpByStepTwo(@Param("did") Integer did);

EmpMapper.xml

<!--List<Emp> getDeptAndEmpByStepTwo(@Param("did") Integer did);-->
<select id="getDeptAndEmpByStepTwo" resultType="emp">
    select * from t_emp where did = #{did}
</select>

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值