8、自定义映射resultMap

本文详细介绍了MyBatis中自定义映射`resultMap`的使用,包括环境配置、字段与属性映射、多对一和一对多映射处理,以及延迟加载和分布查询的实现。通过示例代码展示了如何处理字段不一致的情况,以及如何进行级联查询和分步查询,帮助读者深入理解MyBatis的映射机制。
摘要由CSDN通过智能技术生成


【尚硅谷】SSM框架全套教程-讲师:杨博超

失败,是正因你在距成功一步之遥的时候停住了脚步。

8、自定义映射resultMap

8.1、环境

在mybatis库下创建两个表

1 t_emp表

CREATE TABLE IF NOT EXISTS t_emp(
  `emp_id` int PRIMARY KEY AUTO_INCREMENT,
  `emp_name` varchar(20),
  `age` int NULL,
  `gender` char(1),
  `dept_id` int
);

INSERT INTO t_emp VALUES
(1, '张三', 20, '男', 1),
(2, '李四', 22, '男', 2),
(3, '王五', 23, '男', 3),
(4, '赵六', 26, '男', 1);

2 t_dept表

CREATE TABLE IF NOT EXISTS t_dept(
  `dept_id` int PRIMARY KEY AUTO_INCREMENT,
  `dept_name` varchar(20)
);

INSERT INTO t_dept VALUES
(1, 'A'),
(2, 'B'),
(3, 'C'),
(4, 'D');

3 Emp.java

public class Emp {
    private Integer empId;
    private String empName;
    private Integer age;
    private String gender;
}

4 Dept.java

public class Dept {
    private Integer deptId;
    private String deptName;
}

8.2、使用SQL或全局配置

1 方式一

可以通过为字段起别名的方式,保证和实体类中的属性名保持一致。

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

2 方式二

在MyBatis的核心配置文件中设置一个全局配置信息mapUnderscoreToCamelCase,可以在查询表中数据时,自动将_类型的字段名转换为驼峰。

例如:字段名user_name,设置了mapUnderscoreToCamelCase,此时字段名就会转换为userName。

<settings>
    <setting name="mapUnderscoreToCamelCase" value="true"/>
</settings>

3 EmpMapper.java

// 根据员工Id查询员工
Emp getEmpByEmpId(@Param("empId") int empId);

4 EmpMapper.xml

<!--Emp getEmpByEmpId(@Param("empId") int empId);-->
<select id="getEmpByEmpId" resultType="Emp">
    <!--select emp_id empId, emp_name empName, age, gender
    	from t_emp
    	where emp_id = #{empId}-->
       select emp_id, emp_name, age, gender, dept_id
       from t_emp
       where emp_id = #{empId};
</select>

5 测试

@Test
public void testGetEmpByEmpId() {
    SqlSession sqlSession = MybatisUtils.getSqlSession();
    EmpMapper mapper = sqlSession.getMapper(EmpMapper.class);
    Emp emp = mapper.getEmpByEmpId(1);
    sqlSession.close();
    System.out.println(emp);
}

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

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

  • resultMap:设置自定义映射
  • 属性:
    • id:表示自定义映射的唯一标识
    • type:查询的数据要映射的实体类的类型
  • 子标签:
    • id:设置主键的映射关系
    • result:设置普通字段的映射关系
    • association:设置多对一的映射关系
    • collection:设置一对多的映射关系
  • 属性:
    • property:设置映射关系中实体类中的属性名
    • column:设置映射关系中表中的字段名

1 EmpMapper.xml

<resultMap id="empResultMap" type="Emp">
    <id property="empId" column="emp_id"></id>
    <result property="empName" column="emp_name"></result>
    <result property="age" column="age"></result>
    <result property="gender" column="gender"></result>
</resultMap>
<!--Emp getEmpByEmpId(@Param("empId") int empId);-->
<select id="getEmpByEmpId" resultMap="empResultMap">
    select * from t_emp where emp_id = #{empId}
</select>

8.4、多对一映射处理

1 映射关系

多个员工对应一个部门
多对一:对应的是一个对象

2 Student.java

public class Emp {
    private Integer empId;
    private String empName;
    private Integer age;
    private String gender;
    private Dept dept;
}

3 Dept.java

public class Dept {
    private Integer deptId;
    private String deptName;
}

4 级联方式处理映射关系

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

EmpMapper.java

// 获取员工以及所有对应部门的信息
Emp getEmpAndDeptByEmpId(@Param("empId") Integer empId);

EmpMapper.xml

<resultMap id="empAndDept" type="Emp">
    <id property="empId" column="emp_id"></id>
    <result property="empName" column="emp_name"></result>
    <result property="age" column="age"></result>
    <result property="gender" column="gender"></result>
    <result property="dept.deptId" column="dept_id"></result>
    <result property="dept.deptName" column="dept_name"></result>
</resultMap>
<!--Emp getEmpAndDeptByEmpId(@Param("empId") Integer empId);-->
<select id="getEmpAndDeptByEmpId" resultMap="empAndDept">
    select t1.emp_id, t1.emp_name, t1.age, t1.gender, t1.dept_id, t2.dept_id, t2.dept_name
    from t_emp t1
             left join t_dept t2
                       on t1.dept_id = t2.dept_id
    where t1.emp_id = #{empId};
</select>

测试

@Test
public void testGetEmpAndDeptByEmpId() {
    SqlSession sqlSession = MybatisUtils.getSqlSession();
    EmpMapper mapper = sqlSession.getMapper(EmpMapper.class);
    Emp emp = mapper.getEmpAndDeptByEmpId(1);
    sqlSession.close();
    System.out.println(emp);
}

5 使用association处理映射关系

  • association:处理多对一映射关系(处理实体类类型的属性)
  • property:设置需要处理映射关系的属性的属性名
  • javaType:设置要处理的属性的类型

EmpMapper.xml

<resultMap id="empAndDeptResult" type="Emp">
    <id property="empName" column="emp_name"></id>
    <result property="empName" column="emp_name"></result>
    <result property="age" column="age"></result>
    <result property="gender" column="gender"></result>
    <association property="dept" javaType="Dept">
        <id property="deptId" column="dept_id"></id>
        <result property="deptName" column="dept_name"></result>
    </association>
</resultMap>
<!--Emp getEmpAndDeptByEmpId(@Param("empId") Integer empId);-->
<select id="getEmpAndDeptByEmpId" resultMap="empAndDeptResult">
        select t1.emp_id, t1.emp_name, t1.age, t1.gender, t1.dept_id, t2.dept_id, t2.dept_name
        from t_emp t1
                 left join t_dept t2
                           on t1.dept_id = t2.dept_id
        where t1.emp_id = #{empId};
</select>

测试

@Test
public void testGetEmpAndDeptByEmpId() {
    SqlSession sqlSession = MybatisUtils.getSqlSession();
    EmpMapper mapper = sqlSession.getMapper(EmpMapper.class);
    Emp emp = mapper.getEmpAndDeptByEmpId(1);
    sqlSession.close();
    System.out.println(emp);
}

6 分步查询

property:设置需要处理映射关系的属性的属性名
select:设置分布查询的SQL的唯一表示,(namespace.SQLId或者mapper接口的全类名.方法名)
column:设置分步查询的条件

①查询员工信息

EmpMapper.java

// 获取员工以及所有对应部门的信息
Emp getEmpAndDeptByStepOne(@Param("empId") Integer empId);

EmpMapper.xml

<resultMap id="empAndDeptByStepResultMap" type="Emp">
    <id property="empId" column="emp_id"></id>
    <result property="empName" column="emp_name"></result>
    <result property="age" column="age"></result>
    <result property="gender" column="gender"></result>
    <association property="dept"
                 select="pers.tianyu.mapper.DeptMapper.getEmpAndDeptByStepTow"
                 column="dept_id">
    </association>
</resultMap>
<!--Emp getEmpAndDeptByStepOne(@Param("empId") Integer empId);-->
<select id="getEmpAndDeptByStepOne" resultMap="empAndDeptByStepResultMap">
    select emp_id, emp_name, age, gender, dept_id
    from t_emp
    where emp_id = #{empId};
</select>

②根据员工所对应的部门id查询部门信息

DeptMapper.java

// 查询部门信息
Dept getEmpAndDeptByStepTow(@Param("deptId") Integer deptId);

DeptMapper.xml

<!--Dept getEmpAndDeptByStepTow(@Param("deptId") Integer deptId);-->
<select id="getEmpAndDeptByStepTow" resultType="Dept">
    select dept_id, dept_name
    from t_dept
    where dept_id = #{deptId};
</select>

测试

@Test
public void testGetEmpAndDeptByStepOne() {
    SqlSession sqlSession = MybatisUtils.getSqlSession();
    EmpMapper mapper = sqlSession.getMapper(EmpMapper.class);
    Emp emp = mapper.getEmpAndDeptByStepOne(1);
    sqlSession.close();
    System.out.println(emp);
}

8.5、延迟加载

  • 分步查询的优点:可以实现延迟加载,但是必须在核心配置文件中设置全局配置信息(下滑线转驼峰)。
  • lazyLoadingEnabled:延迟加载的全局开关。当开启时,所有关联对象都会延迟加载。
  • aggressiveLazyLoading:按需加载的全局开关,当开启时,任何方法的调用都会加载该对象的所有属性。否则,每个属性会按需加载。
  • 当开启全局的延迟加载之后,可通过association和collection中的fetchType属性设置当前的分步查询是否使用延迟加载, fetchType=“lazy(延迟加载)|eager(立即加载)”。

1 mybatis-config.xml

<!--延迟加载-->
<setting name="lazyLoadingEnabled" value="true"/>
<!--按需加载-->
<setting name="aggressiveLazyLoading" value="false"/>

2 EmpMapper.xml

在resultMap标签下association标签写设置fetchType=“eager”,可以单个查询不使用延迟加载。

8.6、一对多映射处理

一对多:对应的是一个集合

注意:当设置了部门中有员工信息,就不能设置员工中有部门信息,都设置会出现套娃。

1 collection

  • collection:处理一对多的映射关系(处理集合类型的属性)
  • ofType:设置collection标签所处理的集合属性中存储数据的类型

Dept.java

public class Dept {
    private Integer deptId;
    private String deptName;
    private List<Emp> emps;
}

DeptMapper.xml

<resultMap id="deptEmpMap" type="Dept">
    <id property="deptId" column="dept_id"></id>
    <result property="deptName" column="dept_name"></result>
    <collection property="emps" ofType="Emp">
        <id property="empId" column="emp_id"></id>
        <result property="empName" column="emp_name"></result>
        <result property="age" column="age"></result>
        <result property="gender" column="gender"></result>
    </collection>
</resultMap>

<!--Dept getDeptEmpByDid(@Param("deptId") Integer deptId);-->
<select id="getDeptEmpByDid" resultMap="deptEmpMap">
    select t1.dept_id, t1.dept_name, t2.emp_id, t2.emp_name, t2.age, t2.gender, t2.dept_id
    from t_dept t1
             left join t_emp t2
             	on t1.dept_id = t2.dept_id
    where t1.dept_id = #{deptId}
</select>

2 分布查询

①查询部门信息

DeptMapper.java

// 分布查询部门和部门中的员工
Dept getDeptByStep(@Param("deptId") Integer deptId);

DeptMapper.xml

<resultMap id="deptEmpStep" type="Dept">
    <id property="deptId" column="dept_id"></id>
    <result property="deptName" column="dept_name"></result>
    <collection property="emps"
                select="pers.tianyu.mapper.EmpMapper.getEmpListByDeptId"
                column="dept_id">
    </collection>
</resultMap>
<!--Dept getDeptByStep(@Param("deptId") Integer deptId);-->
<select id="getDeptByStep" resultMap="deptEmpStep">
    select dept_id, dept_name
    from t_dept
    where dept_id = #{deptId};
</select>

②根据部门id查询部门中的所有员工

EmpMapper.java

// 根据部门id查询员工信息
List<Emp> getEmpListByDeptId(@Param("deptId") Integer deptId);

EmpMapper.xml

<!--List<Emp> getEmpListByDeptId(@Param("deptId") Integer deptId);-->
<select id="getEmpListByDeptId" resultType="Emp">
    select emp_id, emp_name, age, gender, dept_id *
    from t_emp
    where dept_id = #{deptId};
</select>
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值