mybatis自定义映射`resultMap`

6_自定义映射resultMap

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

方式一:字段名与属性名不一致,用别名解决
select * from emp;

select eid,emp_name as empName,age,sex,email from emp;别名方式
方式二:核心配置文件中setters标签配

setters标签配置mapUnderscoreToCamelCase属性,值设置为true是开户驼峰命名转换,默认是false是不开启驼峰命名转换

设置名描述有效值默认值
mapUnderscoreToCamelCase是否开启驼峰命名自动映射,即从经典数据库列名 A_COLUMN 映射到经典 Java 属性名 aColumn。`truefalse`
 <settings>
        <setting name="mapUnderscoreToCamelCase" value="true"/>
    </settings>
方式三:自定义映射关系

resultMap自定义标签相关的属性

父级标签

  1. resultMap:设置自定义映射关系
  2. id:唯一标识,不能重复
  3. type:设置映射关系中的实体类类型【就是查询结果给那个JavaBean赋值】

子标签:【重点理解】

  1. id:设置主键的映射关系

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

    属性:

    property:设置映射关系中的属性名,必须是type属性所设置的实体类类型中的属性名【就是type设置JavaBean类中的属性】

    column:设置映射关系中字段名,必须是sql语句查询出字段名【就是查询语句中的字段】

案例:

 <!--
        查询所有员工,并且使用resultMap解决字段名与属性名不一致问题
    -->
    <!--
        resultMap:设置自定义映射关系
        id:唯一标识,不能重复
        type:设置映射关系中的实体类类型
        子标签:
        id:设置主键的映射关系
        result:设置普通字段的映射关系
        属性:
        property:设置映射关系中的属性名,必须是type属性所设置的实体类类型中的属性名
        column:设置映射关系中的字段名,必须是sql语句查询出的字段名
    -->
    <resultMap id="empResultMap" type="Emp">
        <id property="eid" column="eid"/>
        <result property="empName" column="emp_name"/>
        <result property="age" column="age"/>
        <result property="sex" column="sex"/>
        <result property="email" column="email"/>
    </resultMap>

    <select id="getAllEmp" resultMap="empResultMap">
        select * from emp;
    </select>

综合:

Mapper接口

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

Mapper.xml文件

<!--
        查询所有员工,并且使用resultMap解决字段名与属性名不一致问题
    -->
    <!--
        resultMap:设置自定义映射关系
        id:唯一标识,不能重复
        type:设置映射关系中的实体类类型
        子标签:
        id:设置主键的映射关系
        result:设置普通字段的映射关系
        属性:
        property:设置映射关系中的属性名,必须是type属性所设置的实体类类型中的属性名
        column:设置映射关系中的字段名,必须是sql语句查询出的字段名
    -->
    <resultMap id="empResultMap" type="Emp">
        <id property="eid" column="eid"/>
        <result property="empName" column="emp_name"/>
        <result property="age" column="age"/>
        <result property="sex" column="sex"/>
        <result property="email" column="email"/>
    </resultMap>

    <select id="getAllEmp" resultMap="empResultMap">
        select * from emp;
    </select>

    <!--List<Emp> getAllEmp();查询所有员工信息-->
    <select id="getAllEmpOld" resultType="Emp">
        <!--
            由于:`select * from emp;`
            方式字段名`emp_name`与属性`empName`名不一致,
            所以`empName`没有被赋值,返回null值,
            解决方案一:使用别名,为`empName`起与属性一致的别名
            解决方案二:使用全局配置:<setting name="mapUnderscoreToCamelCase" value="true"/>:开启驼峰命名转换
        -->
        <!--
            select * from emp;
            如果需要使用这种方式可以在核心配置文件中,在`setter`标签中
            配置:mapUnderscoreToCamelCase属性,值为ture,默认是false,不支持驼峰命名转换
            <setting name="mapUnderscoreToCamelCase" value="true"/>
        -->
    select eid,emp_name as empName,age,sex,email from emp;<!--别名方式-->
    select * from emp;
    </select>

test

// 查询所有员工信息
    @Test
    public void testGetAllEmp(){
        SqlSession sqlSession = SqlSessionUtils.getSqlSession();
        EmpMapper mapper = sqlSession.getMapper(EmpMapper.class);
        List<Emp> allEmp = mapper.getAllEmp();
        // select * from emp;此方式查询,由于字段名与属性名不一致,
        // 解决方案是:为字段名起别名,为`empName`起与属性一致的别名
        // 如:select eid,emp_name as empName,age,sex,email from emp;
        allEmp.forEach(emp -> System.out.println(emp));
    }

2.多对一映射处理

多对一映射关系,必须要在多的方添加一的对象属性

**案例:**员工对应部门信息,就是典型的多对一映射关系,需要在员工类中添加部门的对象属性【并且添加getter方法和setter方法】

// 处理多对一映射关系,必须要多的一方添加一的方的对象属性
    private Dept dept;

并添加:setter方法和getter方法
方式一:级联属性赋值

Mapper接口

/**
     * 根据ID查询员工信息及对应部门信息
     */
    Emp getEmpAndDeptById(@Param("eid") Integer eid);

Mapper.xml文件

<!--处理多对一映射关系方式一:级联属性赋值-->
    <resultMap id="empAndDeptResultMap" type="Emp">
        <id property="eid" column="eid"/>
        <result property="empName" column="emp_name"/>
        <result property="age" column="age"/>
        <result property="sex" column="sex"/>
        <result property="email" column="email"/>
        <result property="dept.did" column="did"/>
        <result property="dept.deptName" column="dept_name"/>
    </resultMap>


<!--getEmpAndDeptById(@Param("eid") Integer eid);根据ID查询员工信息及对应部门信息-->
    <select id="getEmpAndDeptById" resultMap="empAndDeptResultMap">
        select e.eid,e.emp_name,e.age,e.sex,e.email,d.did,d.dept_name
        from emp as e inner join dept as d on e.did=d.did
        where e.eid=#{eid};
    </select>

test

 // 查询指定ID员工的信息及对应部门信息
    @Test
    public void testGetEmpAndDeptById(){
        SqlSession sqlSession = SqlSessionUtils.getSqlSession();
        EmpMapper mapper = sqlSession.getMapper(EmpMapper.class);
        Emp emp = mapper.getEmpAndDeptById(1);
        System.out.println(emp);
        //使用级联属性赋值:
//        Emp{eid=1, empName='明天', age=21, sex='女', email='123@qq.com', dept=Dept{did=1, deptName='A'}}
    }
方式二:使用association处理映射关系【重点】

例如:

<association property="dept" javaType="Dept">
    <id property="did"   column="did"></id>
    <result property="deptName"  column="dept_name" ></result>
</association>

标签解释:

association父级标签:

  • property: 设置是resultMaptype属性值中的javabean类中dept赋值
  • javaType表示是另一个Javabean

子标签:

id表示为javaType属性中的Dept的属性id值赋值

property表示为javaType属性中的Dept的属性赋值

意思是:先设置javaTyp属性是将查询到的字段值为javaTypejavabean对象赋值,赋值完成后再将javaType赋值的对象给propery的属性赋值

Mapper.xml文件

<!--处理多对一映射关系方式二:association属性解决-->
    <resultMap id="empAndDeptResultMapTwo" type="Emp">
        <id property="eid" column="eid"/>
        <result property="empName" column="emp_name"/>
        <result property="age" column="age"/>
        <result property="sex" column="sex"/>
        <result property="email" column="email"/>
        <association property="dept" javaType="Dept">
            <id property="did" column="did"/>
            <result property="deptName" column="dept_name"/>
        </association>
    </resultMap>

<!--getEmpAndDeptById(@Param("eid") Integer eid);根据ID查询员工信息及对应部门信息-->
    <select id="getEmpAndDeptById" resultMap="empAndDeptResultMapTwo">
        select e.eid,e.emp_name,e.age,e.sex,e.email,d.did,d.dept_name
        from emp as e inner join dept as d on e.did=d.did
        where e.eid=#{eid};
    </select>
方式三:分步查询【最重要推荐使用】

分步查询就是将一条sql语句,分成多步查询获取最终结果

同样需要使用association标签,标签需要这两个属性selectcolumn

标签属性说明:

select:设置分步查询的sql的唯一标识(namespace.SQLId或mapper接口的全类名.方法名)

column:设置分布查询的条件

fetchType:当开启了全局的延迟加载之后,可通过此属性手动控制延迟加载的效果

步骤的解释:

  1. 先是第一步查询到的did【部门id】给第二步查询的条件赋值,使用的属性是column
  2. 第二步查询到的结果给Dept对象赋值
  3. 第三步是将第二的查询到的Dept对象值赋值给指定的属性 如:<association property="dept"

注意是:select是指第二条sql的位置【位置是mapper接口的全类名.方法名

例如:

第一步:
<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>


第二步:【查询到的结果赋值给Dept对象】
<select id="getEmpAndDeptByStepTwo" resultType="Dept">
        select * from dept where did = #{did};
</select>

案例:

Mapper接口

第一步
/**
     * 分步查询员工信息及对应的部门信息
     * 由于每一员工只能对应一个部门,所以需要查询员工信息,
     * 再根据员工对应的部门ID,查询部门信息
     */
    Emp getEmpAndDeptByStepOne(@Param("eid") Integer eid);
    
 
第二步
// 分步查询第二步:根据部门ID查询部门信息
    Dept getEmpAndDeptByStepTwo(@Param("did") Integer did);

Mapper.xml文件

第一步:
<!--处理多对一映射关系方式二:association属性解决-->
    <resultMap id="empAndDeptResultMapTwo" type="Emp">
        <id property="eid" column="eid"/>
        <result property="empName" column="emp_name"/>
        <result property="age" column="age"/>
        <result property="sex" column="sex"/>
        <result property="email" column="email"/>
        <association property="dept" javaType="Dept">
            <id property="did" column="did"/>
            <result property="deptName" column="dept_name"/>
        </association>
    </resultMap>
    
    
 <!--
    getEmpAndDeptByStepOne(@Param("eid") Integer eid);
    分步查询员工及部门信息
-->
    <select id="getEmpAndDeptByStepOne" resultMap="getEmpAndDeptByStepOneResultMap">
        select * from emp where eid = #{eid};
    </select>
    
    
第二步:
<select id="getEmpAndDeptByStepTwo" resultType="Dept">
        select * from dept where did = #{did};
    </select>

test

// 分步查询员工及对应部门信息
    @Test
    public void testGetEmpAndDeptByStep() {
        SqlSession sqlSession = SqlSessionUtils.getSqlSession();
        EmpMapper mapper = sqlSession.getMapper(EmpMapper.class);
        Emp emp = mapper.getEmpAndDeptByStepOne(1);
        System.out.println(emp);
    }
延迟加载【重点】

延迟加载的好处是:我们可以单独调用查询语句的每一步,实现查询之间的独立性【同时也是分步查询的好处】

开启延迟加载需要在核心配置文件中设置全局配置信息:

lazyLoadingEnabled:延迟加载的全局开关。当开启时,所有关联对象都会延迟加载【当我们在全局配置文件中开启加载,在`Mapper.xml`所有的分步查询都是开启的】,lazyLoadingEnabled:设置为true为开启

aggressiveLazyLoading:当开启时,任何方法的调用都会加载该对象的所有属性。 否则,每个属性会按需加载【默认是不开启时[false]】,当开启时我们调用对象中的任何一个属性都会加载所有属性,所以我们需要不开启该属性,达到延迟加载功能[aggressiveLazyLoading:false代表关闭,也是默认值]

开启延迟加载还要与Mapper.xml文件中的fetchType属性搭配使用,一般该属性设置为lazy【也是默认值】,如:fetchType="lazy|eager":lazy表示延迟加载【也是默认值,一般设置该值】,eager表示立即加载

<!--
            select:设置分步查询的sql的唯一标识(namespace.SQLId或mapper接口的全类名.方法名)
            column:设置分布查询的条件
            fetchType:当开启了全局的延迟加载之后,可通过此属性手动控制延迟加载的效果
            fetchType="lazy|eager":lazy表示延迟加载【也是默认值,一般设置该值】,eager表示立即加载
        -->
        <association property="dept"
                     select="com.haikang.mybatis.mapper.DeptMapper.getEmpAndDeptByStepTwo"
                     column="did"
                     fetchType="lazy"
        />

案例:

全局配置文件中

 <settings>
    <!--开启驼峰命名-->
        <setting name="mapUnderscoreToCamelCase" value="true"/>
    <!--开启延迟加载,传入true-->
        <setting name="lazyLoadingEnabled" value="true"/>
    <!--aggressiveLazyLoading:false,表示加载某个属性,不会倒致所有属性加载-->
        <setting name="aggressiveLazyLoading" value="false"/>
    </settings>

Mapper.xml文件

<resultMap id="getEmpAndDeptByStepOneResultMap" type="Emp">
        <id property="eid" column="eid"/>
        <result property="empName" column="emp_name"/>
        <result property="age" column="age"/>
        <result property="sex" column="sex"/>
        <result property="email" column="email"/>
        <!--
            select:设置分步查询的sql的唯一标识(namespace.SQLId或mapper接口的全类名.方法名)
            column:设置分布查询的条件
            fetchType:当开启了全局的延迟加载之后,可通过此属性手动控制延迟加载的效果
            fetchType="lazy|eager":lazy表示延迟加载【也是默认值,一般设置该值】,eager表示立即加载
        -->
        <association property="dept"
                     select="com.haikang.mybatis.mapper.DeptMapper.getEmpAndDeptByStepTwo"
                     column="did"
                     fetchType="lazy"
        />
    </resultMap>

3.一对多映射处理

一对多的关系,例如一个部门有多名员工,一个班级有多名学生

解决方案是:在一的方添加集合并且指定集合的泛型是多方类型【就是JavaBean类型】

// 在一的方添加集合,泛型指定为多的一方类型,并且提供getter和setter方法
    private List<Emp> emps;

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

    public void setEmps(List<Emp> emps) {
        this.emps = emps;
    }
方式一:collection方式

collection标签的说明:

ofType是为集合指定类型

property是为哪个属性赋值

例如

<!--
ofType:设置collection标签所处理的集合属性中存储数据的类型
-->
<collection property="emps" ofType="Emp">
    <id property="eid" column="eid"></id>
    <result property="ename" column="ename"></result>
    <result property="age" column="age"></result>
    <result property="sex" column="sex"></result>
</collection>

案例:

Mapper接口

/**
     *根据部门ID查询该部门中所有员工
     */
    Dept getDeptAndEmpByID(@Param("did")Integer did);

Mapper.xml文件

<resultMap id="DeptAndEmpResultMap" type="Dept">
        <id property="did" column="did"/>
        <result property="deptName" column="dept_name"/>
        <!--
            collection:表示为集合赋值,property表示为Dept类中的emps赋值
            ofType:表示集合的类型是Emp
        -->
        <collection property="emps" ofType="Emp">
            <id property="eid" column="eid"/>
            <result property="empName" column="emp_name"/>
            <result property="age" column="age"/>
            <result property="sex" column="sex"/>
            <result property="email" column="email"/>
        </collection>
    </resultMap>
<!--
   根据部门ID查询对应的部门所有员工
   getDeptAndEmpByID(@Param("did")Integer did);
-->
    <select id="getDeptAndEmpByID" resultMap="DeptAndEmpResultMap">
        select d.did,d.dept_name,e.eid,e.emp_name,e.age,e.sex,e.email
        from dept as d inner join emp as e on d.did=e.did where d.did = #{did};
    </select>

test

// 一对多使用collection解决
    @Test
    public void testGetDeptAndEmpByID(){
        SqlSession sqlSession = SqlSessionUtils.getSqlSession();
        DeptMapper mapper = sqlSession.getMapper(DeptMapper.class);
        Dept dept = mapper.getDeptAndEmpByID(1);
        System.out.println(dept);
        List<Emp> emps = dept.getEmps();
        emps.forEach(emp -> System.out.println(emp));
    }
方式二:分步查询【重点】

分步查询就是将一条sql语句,分成多步查询获取最终结果

同样需要使用association标签,标签需要这两个属性selectcolumn

标签属性说明:

select:设置分步查询的sql的唯一标识(namespace.SQLId或mapper接口的全类名.方法名)

column:设置分布查询的条件

fetchType:当开启了全局的延迟加载之后,可通过此属性手动控制延迟加载的效果

案例:查询指定部门信息及该部门的所有员工

步骤的解释:

  1. 先是第一步查询到的did【部门id】给第二步查询的条件赋值,使用的属性是column
  2. 第二步查询到的结果给Emp对象赋值
  3. 第三步是将第二的查询到的Dept对象值赋值给指定的属性 如:<association property="emps"

注意是:select是指第二条sql的位置【位置是mapper接口的全类名.方法名

案例:查询指定部门信息及该部门的所有员工

Mapper接口

第一步:
/**
     * 分步查询第一步;
     * 根据部门ID查询部门信息及该部门所有员工
     * 先查询出该部门的ID
     * 再根据该部门ID查询该的所有员工
     */
    Dept getDeptAndEmpByStepOnt(@Param("did")Integer did);
    
 
 
 第二步:
 /**
     * 分步查询第二步:
     * 根据部门ID查询该部门对应所有员工
     */
    List<Emp> getDeptAndEmpByStepTwo(@Param("did") Integer did);

Mapper.xml文件

 <resultMap id="DeptAndEmpByStepOneResultMap" type="Dept">
        <id property="did" column="did"/>
        <result property="deptName" column="dept_Name"/>
        <!--
            select:设置分步查询的sql的唯一标识(namespace.SQLId或mapper接口的全类名.方法名)
            column:设置分布查询的条件
            fetchType:当开启了全局的延迟加载之后,可通过此属性手动控制延迟加载的效果
            fetchType="lazy|eager":lazy表示延迟加载【也是默认值,一般设置该值】,eager表示立即加载
        -->
        <collection property="emps"
                    select="com.haikang.mybatis.mapper.EmpMapper.getDeptAndEmpByStepTwo"
                    column="did"
                    fetchType="lazy"/>
    </resultMap>
<!--
    getDeptAndEmpByStepOnt(@Param("did")Integer did);
    分步查询:第一步先查询出该部门的ID
            第二步再根据该部门ID查询该部门的所有员工
-->
    <select id="getDeptAndEmpByStepOnt" resultMap="DeptAndEmpByStepOneResultMap">
        select * from dept where did = #{did};
    </select>

test

// 一对多使用分步查询
    @Test
    public void testGetDeptAndEmpByStep(){
        SqlSession sqlSession = SqlSessionUtils.getSqlSession();
        DeptMapper mapper = sqlSession.getMapper(DeptMapper.class);
        Dept dept = mapper.getDeptAndEmpByStepOnt(1);
        System.out.println(dept);
        List<Emp> emps = dept.getEmps();
        emps.forEach(emp -> System.out.println(emp));
    }

总结

如果查询只是单表时,字段名与属性名不一致,使用别名解决

如果查询是多表时,使用分步查询,实现查询之间的独立性【同时也是分步查询的好处】

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
MybatisPlus是一个基于Mybatis框架的增强工具,可以简化和加速开发过程。在使用MybatisPlus进行数据库操作时,我们可以利用它自带的功能来进行基本的CRUD操作,同时也可以进行自定义映射resultmap自定义映射resultmap可以帮助我们在数据库查询结果与实体类之间建立映射关系,进而方便地操作数据。一般情况下,MybatisPlus会根据数据库字段与实体类属性的对应关系自动进行映射,但在某些特殊情况下,我们可能需要自己来定义映射关系。 要自定义映射resultmap,我们可以通过在实体类中使用注解`@ResultMap`来实现。首先,我们需要在实体类中定义与数据库字段对应的属性,并通过注解`@TableField`来指定数据库字段名。然后,我们可以在实体类中使用注解`@ResultMap`来声明自定义映射resultmap,并指定与数据库字段对应的属性。 例如,有一个数据库表student,包含字段id、name和age,我们可以定义一个实体类Student,其中id属性对应数据库字段id,name属性对应数据库字段name,age属性对应数据库字段age。然后,在Student类中使用注解`@ResultMap`自定义映射resultmap,例如: ```java @Data public class Student { @TableField("id") private Long id; @TableField("name") private String name; @TableField("age") private Integer age; @ResultMap("studentResultMap") public class StudentResultMap{ return new StudentResultMap(){ put("id", "id"); put("name","name"); put("age","age"); } } } ``` 在上述示例中,我们定义了一个名为studentResultMap自定义映射resultmap,并通过`put`方法指定了属性与数据库字段的对应关系。 当我们需要进行数据库查询时,可以通过`@Select`注解或者使用MybatisPlus提供的查询方法来执行查询操作。在查询操作中,我们可以使用自定义映射resultmap来获取查询结果,并将其映射到实体类中。 总之,通过自定义映射resultmap,我们可以灵活地实现数据库查询结果与实体类的映射关系,提高了系统的可维护性和代码的可读性。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值