Mybatis从小白到小黑(四)MyBatis实现复杂环境的Sql查询

简介: 在前面的学习中,我们差不多把Mybatis的基本增删改查、配置文件的配置都讲解了一遍,但是在实际的开发中我们编写的sql不会那么简单,今天就来模拟复杂环境的Sql查询

听说微信搜《Java鱼仔》会让技术提高更快哦


在前面的学习中,我们差不多把Mybatis的基本增删改查、配置文件的配置都讲解了一遍,但是在实际的开发中我们编写的sql不会那么简单,今天就来模拟复杂环境的Sql查询


(一)resultMap结果映射


resultMap 元素是 MyBatis 中最重要最强大的元素,我们之前所写的sql语句,返回值都是简单的基本数据类型或者某一个实体类,比如下面这段sql返回的就是最简单的User类型。

<selectid="getUserById"resultType="com.javayz.pojo.User"parameterType="int">    select * from user where id=#{id};
</select>

现在思考一下下面这种情况,如果实体类中定义的某一个字段和数据库中的字段不一致怎么办

publicclassUser {
privateintid;
privateStringlastname;
//.....}

比如我定义了一个User类,包含id和lastname两个属性,而数据库中这两个字段的名字为id和name。此时再执行查询时结果如下:lastname这个字段直接为null


网络异常,图片无法展示
|


这时候我们就可以使用resultMap来解决这个问题,resultMap可以讲数据库中的字段映射到实体类上。column代表数据库中的字段名,properties代表实体类中的字段名,通过映射之后Mybatis就可以找到对应的字段。

<resultMapid="UserMap"type="User"><!--column代表数据库中的字段名,properties代表实体类中的字段名--><resultcolumn="id"property="id"/><resultcolumn="name"property="lastname"/></resultMap><selectid="getUserById"resultMap="UserMap"parameterType="int">    select id,name from user where id=#{id};
</select>

ResultMap 的设计思想是,对简单的语句做到零配置,对于复杂一点的语句,只需要描述语句之间的关系就行了。


(二)复杂环境下的resultMap使用


在实际的应用场景中,我们会遇到很多比较复杂的业务逻辑,这里resultMap的优势才会被放大。因此我们通过一个案例来实现复杂环境的查询。


//创建教室表
createtable classroom
(  id intnotnull AUTO_INCREMENT,  classname VARCHAR(40)notnull,  PRIMARY KEY (id))//创建学生表
createtable student
(  id intnotnull AUTO_INCREMENT,  name VARCHAR(40)notnull,  classid intnotnull,  PRIMARY KEY (id),  FOREIGN key (classid) REFERENCES classroom(id))//创建一些数据
insertinto classroom VALUES(1,'101班')insertinto classroom VALUES(2,'102班')insertinto student VALUES(1,'Amy',1);insertinto student VALUES(2,'Bob',1);insertinto student VALUES(3,'javayz',1);

在Java的实体类代码中分别建立Student和ClassRoom的类

publicclassStudent {
privateintid;
privateStringname;
privateClassRoomclassRoom;
//省略构造方法、get、set、toString//务必给出无参构造方法}

ClassRoom 类

publicclassClassRoom {
privateintid;
privateStringclassname;
//省略构造方法、get、set、toString//务必给出无参构造方法}

2.1 多对一查询(association)


多对一查询在上面这个案例中表现为多个学生在一个教实中,因此这里的Student类中的第三个变量我们设置为ClassRoom类。


现在我们通过两种方式进行多对一查询:


在mapper路径下创建StudentMapper和studentMapper.xml

其中StudentMapper接口定义一个查询方法:


publicinterfaceStudentMapper {
List<Student>selectAllStudent();
}

查询方法一:通过类似嵌套子查询的方式查询:

<selectid="selectAllStudent"resultMap="StudentAndClassRoom">    select * from student
</select><resultMapid="StudentAndClassRoom"type="Student"><resultproperty="id"column="id"/><resultproperty="name"column="name"/><!--对于复杂类型,对象使用association处理,集合使用collection--><associationproperty="classRoom"column="classid"javaType="ClassRoom"select="getClassRoom"></association></resultMap><selectid="getClassRoom"resultType="ClassRoom">    select * from classroom where id = #{classid}
</select>

首先通过 select * from student 语句查询到所有数据,返回类型通过resultMap进行映射,id和name字段属于基本数据类型字段不需要改动,由于classRoom是一个对象方法,因此需要用association 进行处理,实体类中的属性名为classRoom,与Student表进行连接的字段是classid,Java类是ClassRoom,通过这几个属性,继续使用select查询。

所以上面一段代码总结下来就是两句话:


1、查询student表。


2、通过查询出来的classid值查询classRoom表。


通过测试类测试结果:


@TestpublicvoidtestSelect(){
SqlSessionsqlSession=MybatisUtils.getSqlSession();
StudentMappermapper=sqlSession.getMapper(StudentMapper.class);
List<Student>students=mapper.selectAllStudent();
System.out.println(students);
}

结果如下:

[Student{id=1, name='Amy', classRoom=ClassRoom{id=1, classname='101班'}}, 
Student{id=2, name='Bob', classRoom=ClassRoom{id=1, classname='101班'}},
Student{id=3, name='javayz', classRoom=ClassRoom{id=1, classname='101班'}}]

查询方法二:结果嵌套查询

<selectid="selectAllStudent"resultMap="StudentAndClassRoom">    select s.id sid,s.name sname,c.id cid,c.classname cname
    from student s,classroom c
    where s.classid=c.id
</select><resultMapid="StudentAndClassRoom"type="Student"><resultproperty="id"column="sid"/><resultproperty="name"column="sname"/><associationproperty="classRoom"javaType="ClassRoom"><resultproperty="id"column="cid"/><resultproperty="classname"column="cname"/></association></resultMap>

我个人比较喜欢结果嵌套查询,所有的sql语句写在select语句中,根据结果要返回的值在resultMap中填写对应的数据。


结果与第一种方式相同。


2.2 一对多查询(collection)


修改一下之前的两个实体类,来实现一对多的查询,每个教室里有多个学生:

publicclassStudent {
privateintid;
privateStringname;
privateintclassId;
//省略get、set、toString方法//务必给出无参构造方法}
publicclassClassRoom {
privateintid;
privateStringclassname;
privateList<Student>students;
//省略get、set、toString方法//务必给出无参构造方法}  

接着编写Mapper接口和对应的Mapper.xml

publicinterfaceClassRoomMapper {
List<ClassRoom>getClassRoomByid(@Param("id") intid);
}

在这里我只介绍结果嵌套查询的方式。先通过sql查询出字段信息,再通过resultMap进行展示。

<?xmlversion="1.0" encoding="UTF8" ?><!DOCTYPE mapperPUBLIC "-//mybatis.org//DTD Mapper 3.0//EN""http://mybatis.org/dtd/mybatis-3-mapper.dtd"><mappernamespace="com.javayz.mapper.ClassRoomMapper"><selectid="getClassRoomByid"resultMap="ClassRoomAndStudent"parameterType="int">        select c.id cid,c.classname cname,s.id sid,s.name sname,s.classid classid
        from student s,classroom c
        where s.classid=c.id and c.id=#{id}
</select><resultMapid="ClassRoomAndStudent"type="ClassRoom"><resultproperty="id"column="cid"/><resultproperty="classname"column="cname"/><!--对于集合属性,需要使用collection来实现--><collectionproperty="students"ofType="Student"><resultproperty="id"column="sid"/><resultproperty="name"column="sname"/><resultproperty="classId"column="classid"/></collection></resultMap></mapper>

需要注意几个点,对于集合属性,我们需要使用collection。这里的集合属性中用到了ofType字段,该字段表示集合泛型中所使用的泛型对象类型。


(三)总结


到这里为止,Mybatis的各种查询以及配置用法都讲完了,对于复杂类型,注意以下几点:


1、对象的关联使用association,集合的关联使用collection。


2、官网的resultMap中还有两个参数没有使用:


网络异常,图片无法展示
|


首先讲一下constructor ,constructor主要是用来配置构造方法,默认情况下mybatis会调用实体类的无参构造方法创建一个实体类,如果在实体类中配置了有参构造方法而没有配无参构造,就会报错,此时可用constructor 注入构造方法。


discriminator 鉴别器,可以通过case的值来决定使用哪个resultMap。



相关文章
|
7月前
|
SQL 监控 关系型数据库
一键开启百倍加速!RDS DuckDB 黑科技让SQL查询速度最高提升200倍
RDS MySQL DuckDB分析实例结合事务处理与实时分析能力,显著提升SQL查询性能,最高可达200倍,兼容MySQL语法,无需额外学习成本。
|
7月前
|
SQL 存储 关系型数据库
MySQL体系结构详解:一条SQL查询的旅程
本文深入解析MySQL内部架构,从SQL查询的执行流程到性能优化技巧,涵盖连接建立、查询处理、执行阶段及存储引擎工作机制,帮助开发者理解MySQL运行原理并提升数据库性能。
|
7月前
|
SQL 监控 关系型数据库
SQL优化技巧:让MySQL查询快人一步
本文深入解析了MySQL查询优化的核心技巧,涵盖索引设计、查询重写、分页优化、批量操作、数据类型优化及性能监控等方面,帮助开发者显著提升数据库性能,解决慢查询问题,适用于高并发与大数据场景。
|
8月前
|
SQL XML Java
通过MyBatis的XML配置实现灵活的动态SQL查询
总结而言,通过MyBatis的XML配置实现灵活的动态SQL查询,可以让开发者以声明式的方式构建SQL语句,既保证了SQL操作的灵活性,又简化了代码的复杂度。这种方式可以显著提高数据库操作的效率和代码的可维护性。
485 18
|
6月前
|
SQL 关系型数据库 MySQL
(SQL)SQL语言中的查询语句整理
查询语句在sql中占了挺大一部分篇幅,因为在数据库中使用查询语句的次数远多于更新与删除命令。而查询语句比起其他语句要更加的复杂,可因为sql是数据库不可或缺的一部分,所以即使不懂,也必须得弄懂,以上。
364 0
|
9月前
|
SQL XML Java
MyBatis Mapper中使用limit参数的查询问题
总结而言,MyBatis中使用 `limit`参数的查询可以高度定制并且灵活,基于方法签名和XML映射文件的组合来达成多样化的查询需求。通过参数化查询和动态SQL,MyBatis可以有效地处理各种复杂情境下的数据库操作,并且将SQL语句的维护与业务代码的编写相分离,提升代码的可维护性和可阅读性。
768 13
|
8月前
|
SQL 人工智能 数据库
【三桥君】如何正确使用SQL查询语句:避免常见错误?
三桥君解析了SQL查询中的常见错误和正确用法。AI产品专家三桥君通过三个典型案例:1)属性重复比较错误,应使用IN而非AND;2)WHERE子句中非法使用聚合函数的错误,应改用HAVING;3)正确的分组查询示例。三桥君还介绍了学生、课程和选课三个关系模式,并分析了SQL查询中的属性比较、聚合函数使用和分组查询等关键概念。最后通过实战练习帮助读者巩固知识,强调掌握这些技巧对提升数据库查询效率的重要性。
260 0
|
11月前
|
SQL 关系型数据库 MySQL
凌晨2点报警群炸了:一条sql 执行200秒!搞定之后,我总结了一个慢SQL查询、定位分析解决的完整套路
凌晨2点报警群炸了:一条sql 执行200秒!搞定之后,我总结了一个慢SQL查询、定位分析解决的完整套路
凌晨2点报警群炸了:一条sql 执行200秒!搞定之后,我总结了一个慢SQL查询、定位分析解决的完整套路
|
9月前
|
SQL
SQL中如何删除指定查询出来的数据
SQL中如何删除指定查询出来的数据
|
10月前
|
SQL Java 数据库
解决Java Spring Boot应用中MyBatis-Plus查询问题的策略。
保持技能更新是侦探的重要素质。定期回顾最佳实践和新技术。比如,定期查看MyBatis-Plus的更新和社区的最佳做法,这样才能不断提升查询效率和性能。
557 1
下一篇
开通oss服务