天天看点

Mybatis 查询语句结果集总结

Mybatis 查询语句结果集总结

简单查询-resultType

数据准备

表 Student

字段 注释 SNO 学号 SNAME 学生名字 SSEX 性别 SBIRITHDAY 生日 CLASS 班级

create table TEST.STUDENT

(

SNO varchar(3) not null,

SNAME varchar(4) not null,

SSEX varchar(2) not null,

SBIRTHDAY datetime null,

CLASS varchar(5) null

)

public class Student {

private String SNO;

private String SNAME;

private String SSEX;

private Date SBIRTHDAY;

private String CLASS;

...

}

例子

按照返回数据类型大致分为基础数据类型,JavaBean 和 Map。其中虽然返回的结果行数有单条也有多条,对应的接口返回类型是集合或者单个对象,但是在 xml 映射文件中,resultType 的值是相同的。

指定字段-基础数据类型

接口类:

String querySingleStudent();

List queryAllStudent();

Mapper 文件:

SELECT SNAME FROM TEST.STUDENT LIMIT 1

SELECT SNAME FROM TEST.STUDENT

Map,一般为 hashMap

Map queryStudentMap();

List> queryAllStudentMap();

其中:

hashmap 为简写,也可以使用 java.util.HashMap 全称

默认情况下,结果集中值为 null 时, 不会增加映射对象的 setter 方法, (map 对象时为 put)。该行为可以在 mybatis-config.xml 配置文件中设置 覆盖默认设定。

JavaBean

Student querySingleStudentBean();

List queryAllStudentBean();

resultType="student" 为 Student.java 的别名,也可以是全限定名。别名在 mybatis-config.xml 配置文件中设置:

但是如果 JavaBean 文件很多,不想一个个指定,也可以使用 package 标签 设置mybatis自动扫描,别名即为类名的小写。

复杂查询 resultMap

对于一般的查询语句,resultType 足够了。对于多表查询等情况,就要请出 resultMap 了。

数据库字段和 java 数据类型映射关系

数据库字段类型 jdbcType 和 java 数据类型 并不是一一对应的关系,而且不同数据库类型也不尽相同。而 mybatis 将 TypeHandler 作为两者之间的映射关系。大部分情况下都是没有问题的,但是并非能覆盖所有的情况,特殊情况下可以使用 resultMap 自定义这种映射关系。

举个例子,数据库 LongVarchar 字段类型对应 java 中的 String 类型。但是在 DB2 数据库中,查询的 LongVarchar 类型的字段,在 mybatis 中被识别成 jdbcType 为 BLOB。有两种解决方法,第一种是在 SQL 中对该字段使用 CAST 转换为 VARCHAR(长度)类型。另一种是使用 resultMap:

标签中使用 resultMap 指定返回集合。注意 resultMap 和 resultType 不能同时使用

标签

id 和 select 标签指定映射关系

type 和 resultType 一样为返回类型的全限定名或者别名

autoMapping 自动映射关系,在这里目的只是修改一个字段,其他自动采用自动完成映射关系

property 为 java 变量名

column 为数据库字段名

jdbcType 这里指定为 VARCHAR

id

字段的映射关系的标签即有,也有,在 mybatis 文档中指出不使用id,会造成性能下降,因此将主键字段使用 id 标签是推荐的做法。但是如果不存在主键呢,当你在 ResultMap 只提供了部分字段而不是全部字段,即使使用了 autoMapping 属性,那么 mybatis 会按照你提供的字段名进行去重。那么在使用 resultMap 的时候,最优选择是:

如果表存在主键,就使用id标签指定

如果表不存在主键,要么不配置字段的映射关系,使用 autoMapping 属性自动映射;或者不使用 autoMapping 将所有字段罗列。

多表关联查询

在 resultType 的例子中都只涉及到一张表,如果涉及多张表关联查询呢。我们可以简单的将所有列映射到 hashmap 的键值上。

但是 HashMap 不是一个很好的领域模型。 你的程序更可能会使用 JavaBean 或 POJO(Plain Old Java Objects,普通 Java 对象)作为领域模型。

因此这里均采用 JavaBean 作为领域模型。增加一个成绩表 Score

字段 注释 SNO 学号 CNO 课程编号 DEGREE 成绩

create table SCORE

CNO varchar(5) not null,

DEGREE decimal(10, 1) not null

public class Score {

private String CNO;

private Double DEGREE;

一对一关系

这里的一对多关系是两个表字段一一对应,一个学生的某门课的成绩是唯一确定的。 在一一对应的情况下要在 resultMap 中使用 标签。

在 Student.java 中增加字段 Score

private Score score;

public Score getScore() {

return score;

public void setScore(Score score) {

this.score = score;

有两种使用情况,第一种为嵌套查询,即前一个 SQL 查询结果集中的字段作为参数传递给下一个 SQL。第二种情况为嵌套结果集,即两个表做关联查询,将结果集映射到多个 JavaBean 文件。

嵌套查询

select SNO,SNAME

from test.STUDENT

select degree from test.SCORE

where sno = #{sno}

在标签中

property 指向了 Student.java 中新增的 score 字段。

column 指定了作为参数传递给下一个查询SQL的字段,需要注意的是对于传递单个字段的情况,mybatis 只是简单的将 #{参数} 替换为占位符 ?, 然后执行 resultSet.getString(columnName),没有进行参数匹配,因此第二个 SQL 中 #{} 中写任何字符都可以;如果需要传递多个字段,使用 column = " {prop1=col1,prop2=col2} ",这种情况下会以参数对象的形式来传递。

select 指定了下一个 SELECT 语句

另外需要注意的是这种嵌套查询对于大型结果集和列名并友好,存在 

N+1

 的问题,因为下一条 SQL 会执行 N 次去循环查询,使用关联查询更合适。再者也可以开启 mybatis 的

懒查询

功能,嵌套的 SQL 不是一口气顺序执行完,而是在使用的时候才会执行下一条 SQL。例如执行student.getScore().getSNO()才会执行queryScore的 SQL。默认情况下没有开启,需要在配置文件中设置

设置参数 描述 默认值 lazyLoadingEnabled 延迟加载的全局开关,特定关联关系中可通过设置 fetchType 属性来覆盖该项的开关状态 false aggressiveLazyLoading 当开启时,任何方法的调用都会加载该对象的所有属性。否则,每个属性会按需加载 false (true in ≤3.4.1)

也可以在标签中设置 fetchType = “lazy” 开启懒加载,会覆盖全局的参数设置。

嵌套结果集

对于多表关联查询,一般在 SQL 中使用别名来避免字段名的重复。mybatis 要做的是将别名正确的映射到 JavaBean 属性上。

SELECT SNAME, SSEX, CLASS, ST.SNO, SC.SNO AS SC_SNO

FROM test.student st INNER JOIN test.score sc

ON st.sno = sc.sno

where CNO = '3-105';

通过设置标签指定了表列名和属性之间的映射关系。但这样如果字段很多,会需要一一指定,标签提供了columnPrefix属性,指定别名的前缀,这样可以重用resultMap

一对多关系

除了一对一的关系,还有一对多的关系,比如这里一个学生Student 对应多门课的成绩。 一对多对应的情况下要在 resultMap 中使用 标签。首先需要调整 JavaBean 文件中两个表之间的关系。

private List score;

public List getScore() {

public void setScore(List score) {

以嵌套结果集为例

SELECT SNAME,SSEX,CLASS,ST.SNO,SC.SNO AS SC_SNO

注意到相比 association 多了一个属性ofType,是用来表示 List 集合中的类型的。其他属性的用法同 association 是一样的。

Java高架构师、分布式架构、高可扩展、高性能、高并发、性能优化、Spring boot、Redis、ActiveMQ、Nginx、Mycat、Netty、Jvm大型分布式项目实战学习架构师视频免费学习加群:835638062 点击链接加入群聊【Java高级架构】:https://jq.qq.com/?_wv=1027&k=5S3kL3v