MyBatis高级映射ResultMap解决属性问题

 更新时间:2023年02月20日 14:07:37   作者:绿仔牛奶_  
对于数据库中对表的增删改查操作,我们知道增删改都涉及的是单表,而只有查询操作既可以设计到单表操作又可以涉及到多表操作,所以对于输入映射parameterType而言是没有所谓的高级映射的,也就是说高级映射只针对于输出映射

ResultMap结果映射解决复杂属性

之前我们提到了用resultMap解决数据表中字段名与bean属性名不一致的问题,这是resultMap的一种简单实现。下面我们来看如何利用ResultMap来解决更复杂的属性问题

场景:当我们需要联查两张表的时候,通常会在sql层面对两个表进行外键关联。那么设置了外键的从表对应的实体Bean中就需要定义一个对应主表的实例对象。

多对一关系处理

按照查询嵌套

示例:

// 学生表  从表
public class Student {
    private int id;
    private String name;
    private Teacher teacher; // 定义主表对应bean实例
// 教师表  主表
public class Teacher {
    private int id;
    private String name;
  //teacher接口中定义方法
  @Select("select name from teacher where id = #{tid}")
    Teacher getTeacherById(@Param("tid") int id);
  // student接口中定义方法
    List<Student>  getStudent();

sql:

-- 可以直接利用多表联查sql  但是最终无法正确输出teacher类信息
select * from student s join teacher t on s.tid = t.id;
-- 将上面的sql拆开成两句  先查询到学生信息  用学生的tid字段对应教师的id查询教师
select * from student;
select * from teacher where id = #{tid}

打印日志:

Setting autocommit to false on JDBC Connection [com.mysql.cj.jdbc.ConnectionImpl@79da8dc5]
==>  Preparing: select * from student;
==> Parameters: 
<==    Columns: id, name, tid
<==        Row: 1, 小子三, 1
<==        Row: 2, 小子四, 1
<==        Row: 3, 小子五, 1
<==        Row: 4, 小子六, 1
<==        Row: 5, 小子七, 1
<==        Row: 6, 小子八, 1
<==      Total: 6
Student{id=1, name='小子三', teacher=null}
Student{id=2, name='小子四', teacher=null}
Student{id=3, name='小子五', teacher=null}
Student{id=4, name='小子六', teacher=null}
Student{id=5, name='小子七', teacher=null}
Student{id=6, name='小子八', teacher=null}

可以很清晰的看出sql一共只执行了一条,而根据学生表tid字段查询教师信息的sql根本就没有运行

下面我们对select * from teacher where id = #{tid}这句sql返回的结果配置,利用resultMap为其配置合理的结果集来接收查询到的结果

resultMap及sql配置如下:

<resultMap id="studentTeacher" type="student">
  <!--      普通映射  -->
  <result column="id" property="id"/>
  <result column="name" property="name"/>
  <!--      复杂映射 association对象  collection集合 -->
  <association property="teacher" column="tid" javaType="teacher" select="getTeacherById"/>
  <!--    student表中tid字段对应实体类student中的teacher属性 对应程序中的teacher类型 执行select语句    -->
</resultMap>

最终打印结果如下:

Setting autocommit to false on JDBC Connection [com.mysql.cj.jdbc.ConnectionImpl@79da8dc5]
// 执行sql1
==>  Preparing: select * from student;
==> Parameters: 
<==    Columns: id, name, tid
<==        Row: 1, 小子三, 1
// 执行sql1
====>  Preparing: select * from teacher where id = ?
====> Parameters: 1(Integer)
<====    Columns: id, name
<====        Row: 1, 秦老师
<====      Total: 1
<==        Row: 2, 小子四, 1
<==        Row: 3, 小子五, 1
<==        Row: 4, 小子六, 1
<==        Row: 5, 小子七, 1
<==        Row: 6, 小子八, 1
<==      Total: 6
// 最终teacher也以对象的形式打印出来
Student{id=1, name='小子三', teacher=Teacher{id=1, name='秦老师'}}
Student{id=2, name='小子四', teacher=Teacher{id=1, name='秦老师'}}
Student{id=3, name='小子五', teacher=Teacher{id=1, name='秦老师'}}
Student{id=4, name='小子六', teacher=Teacher{id=1, name='秦老师'}}
Student{id=5, name='小子七', teacher=Teacher{id=1, name='秦老师'}}
Student{id=6, name='小子八', teacher=Teacher{id=1, name='秦老师'}}

按照结果嵌套

studentMapper.xml配置resultMap如下:

<!-- 按照结果嵌套 -->
<select id="getStudent2" resultMap="studentTeacher2">
  select s.id sid,s.name sname,t.id tid,t.name tname from student s join teacher t on s.tid = t.id;
</select>
<resultMap id="studentTeacher2" type="student">
  <result column="sid" property="id"/>
  <result column="sname" property="name"/>
  <association property="teacher" javaType="teacher">
    <result column="tid" property="id"/>
    <result property="name" column="tname"/>
  </association>
</resultMap>

如果采用结果嵌套配置,此时不论bean类属性是否是基本类型都需要用result进行映射,否则输出结果就会采用默认值

一对多关系处理

一对多关系处理,依旧以上述老师和学生为例。但是实体类需要修改,如下:

public class Teacher {
  private int id;
  private String name;
  private List<Student> student;
public class Student {
  private int id;
  private String name;
  private int tid;

一个老师下对应多个学生,所以我们定义一个集合用于存储学生

下面尝试获取指定老师下的所有学生信息及该老师信息

按照结果嵌套

程序:

// TeacherMapper
// 指定老师下面的所有学生
Teacher getTeaById(@Param("teaId") int id);

resultMap配置

<select id="getTeaById" resultMap="TeaStu">
  select s.id sid, s.name sname, t.name tname, t.id tpid,s.tid
  from student s ,teacher t
  where t.id = s.tid and t.id = #{teaId};
</select>
<resultMap id="TeaStu" type="Teacher">
  <result column="tpid" property="id"/>
  <result column="tname" property="name"/>
  <collection property="student" ofType="student">
    <result column="sid" property="id"/>
    <result column="sname" property="name"/>
    <result column="tid" property="tid" />
  </collection>
</resultMap>

因为复杂属性的类型为集合,所以我们在配置resultMap结果集映射时不再使用association对象,换成collection集合。在配置collection与association不同的是将JavaType(Java类型)换成了OfType其他依旧不变

按照查询嵌套

TeacherMapper.xml配置resultMap

<select id="getTeaById" resultMap="TeaStu2">
  select id,name from teacher where id = #{teaId}
</select>
<resultMap id="TeaStu2" type="teacher">
  <result column="id" property="id"/>
  <result column="name" property="name"/>
  <collection property="student" javaType="ArrayList" ofType="student" select="getStuList" column="id"/>
</resultMap>
<select id="getStuList" resultType="student">
  select id,name,tid from student where tid = #{tid}
</select>

小结:个人感觉,按照查询嵌套虽然一定程度上简化了sql语句的编写,但是针对resultMap的配置极其复杂,如果使用次数多可能还好。建议使用按照结果嵌套,sql语句编写虽然复杂一些但是只要基础扎实都是有理可循的,而且sql的编写你可以在数据库中进行调试,选择最优sql,并且对于结果集的映射配置也比较简单,容易理解。

也可能是初学所以觉得按照子查询会有点难度,总之还是水平太低了

到此这篇关于MyBatis高级映射ResultMap解决属性问题的文章就介绍到这了,更多相关MyBatis高级映射ResultMap内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • eclipse实现可认证的DH密钥交换协议

    eclipse实现可认证的DH密钥交换协议

    这篇文章主要介绍了eclipse实现可认证的DH密钥交换协议,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2020-06-06
  • Mybatis-Plus实现SQL拦截器的示例

    Mybatis-Plus实现SQL拦截器的示例

    这篇文章主要介绍了Mybatis-Plus实现一个SQL拦截器,通过使用SQL拦截器,开发人员可以在执行SQL语句之前或之后对其进行修改或记录,从而更好地控制和优化数据库操作,对Mybatis-Plus SQL拦截器相关知识感兴趣的朋友一起看看吧
    2023-05-05
  • 使用Springboot整合Apollo配置中心

    使用Springboot整合Apollo配置中心

    这篇文章主要介绍了使用Springboot整合Apollo配置中心的操作,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2021-07-07
  • java泛型详解

    java泛型详解

    本文主要介绍了java泛型的相关知识。具有很好的参考价值。下面跟着小编一起来看下吧
    2017-03-03
  • MyBatis中传入参数parameterType类型详解

    MyBatis中传入参数parameterType类型详解

    这篇文章主要给大家介绍了关于MyBatis中传入参数parameterType类型的相关资料,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下
    2018-04-04
  • Spring中@Transactional注解的属性说明

    Spring中@Transactional注解的属性说明

    这篇文章主要介绍了Spring中@Transactional注解的属性说明,@Transactional 是声明式事务管理 编程中使用的注解,@Transactional 注解应该只被应用到 public 方法上,这是由 Spring AOP 的本质决定的,需要的朋友可以参考下
    2023-11-11
  • Spring-Validation 后端数据校验的实现

    Spring-Validation 后端数据校验的实现

    这篇文章主要介绍了Spring-Validation 后端数据校验的实现,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2020-07-07
  • 拳皇(Java简单的小程序)代码实例

    拳皇(Java简单的小程序)代码实例

    这篇文章主要介绍了拳皇Java简单小程序,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2019-03-03
  • Spring Boot的listener(监听器)简单使用实例详解

    Spring Boot的listener(监听器)简单使用实例详解

    监听器(Listener)的注册方法和 Servlet 一样,有两种方式:代码注册或者注解注册。接下来通过本文给大家介绍Spring Boot的listener(监听器)简单使用,需要的朋友可以参考下
    2017-04-04
  • Java入门基础之Java的基本语法与Java所支持的数据类型

    Java入门基础之Java的基本语法与Java所支持的数据类型

    这篇文章主要介绍了Java入门基础之Java的基本语法与Java所支持的数据类型,熟悉语法和数据类型通常是了解一种编程语言的开始,需要的朋友可以参考下
    2016-02-02

最新评论