天天看点

MyBatis的多表查询笔记

随着学习的进步,需求的提高,我们在实际开发中用的最多的还是多表查询,就让我们一起学习MyBatis中的多表查询。

MyBatis的多表查询笔记
MyBatis的多表查询笔记
MyBatis的多表查询笔记

这次使用的是Spring+MyBatis整合的,具体的规范我也不是很清楚,所以并不清楚项目结构是否规范,最终项目结构以实际需求大纲为主。

Dao层

ClazzMapper、StudentMapper作为MyBatis的*Mapper.xml的接口

Tool为提供Service层服务的接口,ToolImpl为该接口的实现类

POJO

两个表的实体类,并根据业务需求添加了额外的属性。

并不知道需不需要Tool这个结构,学习阶段没有去实际开发过项目,自己感觉需要吧。。。为service提供服务(假设是个web项目)。

我们需要用MyBatis实现多表查询的方法主要有两种:业务代码实现、SQL语句实现

多表查询一般有几种关系?多表查询分为3种关系:

一对一

一对多

多对多

我们在这里不讨论多对多,因为需要第三方表才能实现。我们讨论前两种!

查询所有学生对应的班级信息(一对一)

查询每个班级中所在学生的信息(一对多)

业务代码实现分两种:一种是使用<code>resultType</code>,另一种是使用<code>resultMap</code>,其实这两者说的是Mapper.xml文件中的操作语句的标签属性名。

其实在我们学习MyBatis的时候resultType我们经常使用到(如果忘记了可以百度),其作用就是表明查询语句中使用什么数据类型来接收查询到的数据。

什么是业务代码实现MyBatis的多表查询?

业务代码就是用代码实现的查询,有时候多表查询并不一定是需要外键连接,两张表并没有外交连接,但是需求可能就需要结合两张表,我们可以用代码去控制查询时表与表之间的关系。具体怎么操作呢?假如我们现在要实现第一个业务需求(一对一),先写两条查询语句:

我们可以先将所有学生信息查询出来,因为t_student的croom就t_class表中的cid字段名,然后再用for循环将每个学生的croom作为条件,查询croom对应的班级信息,再存入Student的Clazz属性,最后输出即可。

这样我们就实现了业务代码的多表查询,特点是没有用到连接查询,我们每个查询语句都是单表查询,但是我们利用了java业务代码结合查询语句实现了多表查询。

输出结果:

我们可以看到日志输出一共有7+1(8)条查询记录。这种方法我们是通过用java代码实现两张表的关系,所以执行的sql语句有8条

业务代码:

查看日志输出结果:

结果是执行的查询记录有7+1(8)条。我们这次并没有用上面的业务代码实现多表查询,而是借助了MyBatis的标签——resultMap实现了多表查询。resultMap标签的属性介绍都写在了Mapper.xml文件中。

结合上诉两种方式小结:

两种方式查询的结果是一样的,并且都查询了7+1条语句,7条执行班级的条件查询,1条执行学生的所有查询,简称:"N+1"方式的多表查询,先查询出某个表的全部信息,根据这个表的信息查询出另一个表的信息。

两者都是业务代码实现多表查询,总的来说就是将平常的连接查询语句拆成了多个单表查询,用来实现,虽然业务代码多了一点,但是相对于用一条SQL执行多表查询来说某种程度降低了难度,比如:用一条SQL实现多表查询,如果需求很复杂,这个时候我们可以将其部分拆解为单表查询结合起来,只要适当合理,不仅仅可以降低难度,也可以方便维护。

区分resultMap和resultType的区别:

resultType:很简单,就是定义返回结果值的类型

resultMap:推荐还是看官方文档吧,我才学疏浅总结的不好怕带歪,总的来说resultMap也是MyBatis的很重要的核心之一,因为官方就是这样形容的:resultMap元素是 MyBatis 中最重要最强大的元素。它可以让你从 90% 的 JDBC ResultSets 数据提取代码中解放出来,并在一些情形下允许你进行一些 JDBC 不支持的操作

上面这两种就是使用业务装配的方式实现了多表查询(多个单表查询实现多表查询)

既然是多表查询,那么肯定就有用一条SQL语句查询实现多表查询的。

直接上代码:

再来看看我们调用的结果:

可以看到结果是一样的,但是执行的sql语句只有一句。这就是用SQL语句实现多表查询,特点就是用了连接查询。用的依然是resultMap,可以看出resultMap有多重要了!

上诉介绍了3中不同的方式实现多表查询,多数使用第二种和第三种,甚至可能搭配使用。

在第二种方式中如果实体类的属性名与查询结果最终的字段名相同,MyBatis可以帮我们自动映射到实体类中,如果查询时设置了别名,就必须用result标签手动指定赋值。

第三章方式中就不能省略result标签,你想从resultMap取什么值就必须用result标签表明,如果省略不写,MyBatis不会自动帮我们装配,所以我们必须指明。注意:如果两张表出现了相同字段名,我们必须在SQL语句中使用别名将他们区分,否则MyBatis会以靠前的字段名数据赋值。

既然单个对象赋值字段名是<code>association</code>,那么如果是一对多中的集合对象呢?我们怎么做?这个时候我们就需要换一个标签——<code>collection</code>,并且将javaType属性换成ofType属性名即可,ofType的属性我们可以看作是集合的泛型类型,其他的用法一样,我们这一点必须要区分取开来。

如果我们使用了resultMap,我们就要将select中的resultType换成resultMap,且两者不能共存。

更多的我们应该结合官方博客的部分参考来帮助我们学习理解!