Mybatis查询语句结果集的总结大全

简单查询-resultType

数据准备

字段 注释
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
)
<!--Bean 文件-->
public class Student {
 private String SNO;
 private String SNAME;
 private String SSEX;
 private Date SBIRTHDAY;
 private String CLASS;

 <!--get 和 set 方法-->
 ...
}

例子

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

1、指定字段-基础数据类型

接口类:

<!--单条结果集-->
String querySingleStudent();
<!--多条结果集-->
List<String> queryAllStudent();

Mapper 文件:

<!--单条结果集-->
<select id="querySingleStudent" resultType="string">
 SELECT SNAME FROM TEST.STUDENT LIMIT 1
</select>
<!--多条结果集-->
<select id="queryAllStudent" resultType="string">
 SELECT SNAME FROM TEST.STUDENT
</select>

2、Map,一般为 hashMap

接口类:

<!--单条结果集-->
Map<String, Object> queryStudentMap();
<!--多条结果集-->
List<Map<String, Object>> queryAllStudentMap();
复制代码Mapper 文件:
<!--单条结果集-->
<select id="queryStudentMap" resultType="hashmap">
 SELECT SNAME FROM TEST.STUDENT LIMIT 1
</select>
<!--多条结果集-->
<select id="queryAllStudentMap" resultType="hashmap">
 SELECT SNAME FROM TEST.STUDENT
</select>

其中:

  • hashmap 为简写,也可以使用 java.util.HashMap 全称
  • 默认情况下,结果集中值为 null 时, 不会增加映射对象的 setter 方法, (map 对象时为 put)。该行为可以在 mybatis-config.xml 配置文件中设置
    <setting name="callSettersOnNulls" value="true"/> 覆盖默认设定。

3、JavaBean

接口类:

<!--单条结果集-->
Student querySingleStudentBean();
<!--多条结果集-->
List<Student> queryAllStudentBean();

Mapper 文件:

<!--单条结果集-->
<select id="queryStudentMap" resultType="student">
 SELECT SNAME FROM TEST.STUDENT LIMIT 1
</select>
<!--多条结果集-->
<select id="queryAllStudentMap" resultType="student">
 SELECT SNAME FROM TEST.STUDENT
</select>

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

<typeAliases>
 <typeAlias type="com.bean.Student" alias="student"/>
 ...
</typeAliases>

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

<typeAliases>
 <package name="包名"/>
</typeAliases>

复杂查询 resultMap

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

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

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

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

<resultMap id="resultMapDemo" type="" autoMapping="true">
 <result property="" column="" jdbcType="VARCHAR" />
</resultMap>

<select id="demoID" resultMap="resultMapDemo">
...
<select>

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

2、<resultMap> 标签

  • id 和 select 标签指定映射关系
  • type 和 resultType 一样为返回类型的全限定名或者别名
  • autoMapping 自动映射关系,在这里目的只是修改一个字段,其他自动采用自动完成映射关系

3、<result> 标签

  • 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
(
 SNO varchar(3) not null,
 CNO varchar(5) not null,
 DEGREE decimal(10, 1) not null
)
<!--Bean 文件-->
public class Score {
 private String SNO;
 private String CNO;
 private Double DEGREE;
 <!--get 和 set 方法-->
 ...
}

一对一关系

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

在 Student.java 中增加字段 Score

<!--Student.java-->
private Score score;
public Score getScore() {
 return score;
}
public void setScore(Score score) {
 this.score = score;
}

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

嵌套查询

<resultMap id="allstudentResultMap" type="student">
 <!--指定第二个 SELECT 语句,和传递的字段-->
 <association property="score" column="sno" select="queryScore" />
</resultMap>

<!--第一个 SQL -->
<select id="queryAllStudent" resultMap="allstudentResultMap">
 select SNO,SNAME
 from test.STUDENT
</select>

<!--第二个 SQL-->
<select id="queryScore" resultType="score">
 select degree from test.SCORE
 where sno = #{sno}
</select>

在标签中

  • 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)
<!--mybatis-config.xml-->
<setting name="lazyLoadingEnabled" value="true"/>
<setting name="aggressiveLazyLoading" value="false"/>

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

嵌套结果集

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

<!--嵌套结果-->
<resultMap id="associationDemoMap" type="student" autoMapping="true">
 <association property="score" javaType="score">
  <result property="SNO" column="SC_SNO"/>
 </association>
</resultMap>

<select id="queryStudentScore" resultMap="associationDemoMap">
 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';
</select>

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

<resultMap id="associationDemoMap" type="student" autoMapping="true">
 <!--columnPrefix 指定别名的前缀-->
 <association property="score" resultMap="anotherMap" columnPrefix="SC_" />
</resultMap>

<!--方便重用-->
<resultMap id="anotherMap" type="score" autoMapping="true">
</resultMap>

一对多关系

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

<!--Student.java-->
private List<Score> score;
public List<Score> getScore() {
 return score;
}
public void setScore(List<Score> score) {
 this.score = score;
}

以嵌套结果集为例

<resultMap id="collectionDemoMap" type="student" autoMapping="true">
 <!--多出了 ofType 属性-->
 <collection property="score" ofType="score">
  <result property="SNO" column="SC_SNO"/>
 </collection>
</resultMap>

<select id="queryStudentScore" resultMap="collectionDemoMap">
 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
</select>

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

总结

以上就是这篇文章的全部内容了,希望本文的内容对大家的学习或者工作具有一定的参考学习价值,如果有疑问大家可以留言交流,谢谢大家对我们的支持。

(0)

相关推荐

  • Mybatis模糊查询和动态sql语句的用法

    Mybatis 模糊查询和动态sql语句 模糊查询 对数据库最常用的操作就是查询了,但是如何使用Mybatis进行模糊查询呢?下面先看一个简单的模糊查询 <select id="select01" resultMap="BasicResultMap"> SELECT * FROM oa_employee WHERE emp_name LIKE #{asd} </select> 这是一条伪模糊查询, 因为没有实现真正的模糊 "%&qu

  • Mybatis传递多个参数进行SQL查询的用法

    PS:ibatis3如何传递多个参数有两个方法:一种是使用java.Map,另一种是使用JavaBean. 当只向xxxMapper.xml文件中传递一个参数时,可以简单的用"_parameter"来接收xxxMapper.java传递进来的参数,并代入查询,比如说这样: (1)xxxMapper.java文件中这样定义: List<String> selectAllAirportCode(Boolean mapping); (2)这时在对应的xxxMapper.xml文件

  • mybatis查询语句揭秘之参数解析

    一.前言 通过前面我们也知道,通过getMapper方式来进行查询,最后会通过mapperMehod类,对接口中传来的参数也会在这个类里面进行一个解析,随后就传到对应位置,与sql里面的参数进行一个匹配,最后获取结果.对于mybatis通常传参(这里忽略掉Rowbounds和ResultHandler两种类型)有几种方式. 1.javabean类型参数 2.非javabean类型参数 注意,本文是基于mybatis3.5.0版本进行分析. 1.参数的存储 2.对sql语句中参数的赋值 下面将围绕

  • mybatis查询语句的背后揭秘

    一.前言 在先了解mybatis查询之前,先大致了解下以下代码的为查询做了哪些铺垫,在这里我们要事先了解,myabtis会默认使用DefaultSqlSessionFactory作为sqlSessionFactory的实现类,而sqlSession的默认实现类为DefaultSqlSession public static SqlSessionFactory getSessionFactory() throws IOException { Reader reader = Resources.ge

  • Mybatis实现增删改查及分页查询的方法

    MyBatis的前身就是iBatis.是一个数据持久层(ORM)框架. MyBatis是支持普通SQL查询,存储过程和高级映射的优秀持 久层框架.MyBatis消除了几乎所有的JDBC 代码和参数的手工 设置以及结果集的检索.MyBatis使用简单的XML或注解用于 配置和原始映射,将接口和Java 的POJOs(Plan Old Java Objects,普通的Java 对象)映射成数据库中的记录.每个 MyBatis应用程序主要都是使用SqlSessionFactory实例的,一个 SqlS

  • Mybatis查不到数据查询返回Null问题

    mybatis突然查不到数据,查询返回的都是Null,但是 select count(*) from xxx查询数量,返回却是正常的. Preparing: SELECT id,a9004,a9005,a9015 FROM a90 where a9010 = ? ORDER BY id LIMIT 1 [DEBUG] org.apache.ibatis.logging.jdbc.BaseJdbcLogger.debug(BaseJdbcLogger.java:139):http-bio-8080

  • Mybatis多表关联查询的实现(DEMO)

    概要 本节要实现的是多表关联查询的简单demo.场景是根据id查询某商品分类信息,并展示该分类下的商品列表. 一.Mysql测试数据 新建表Category(商品分类)和Product(商品),并插入几条测试数据. create table Category ( Id int not null auto_increment, Name varchar(80) null, constraint pk_category primary key (Id) ); INSERT INTO category

  • MyBatis中的模糊查询语句

    其实就只有一条sql语句 <select id = "search" resultType = "material"> select material_id,material_num,material_name,material_type,material_model,id from material where material_name like '%${value}%' or material_num like '%${value}%' </

  • mybatis查询语句揭秘之封装数据

    一.前言 继上一篇mybatis查询语句的背后,这一篇主要围绕着mybatis查询的后期操作,即跟数据库交互的时候.由于本人也是一边学习源码一边记录,内容难免有错误或不足之处,还望诸位指正,本文只可当参考作用.谨记! 二.分析 继上一篇博文的查询例子,mybatis在最后的查询最终会走SimpleExecutor类的doQuery方法, @Override public <E> List<E> doQuery(MappedStatement ms, Object parameter

  • 详解MyBatis直接执行SQL查询及数据批量插入

    一.直接执行SQL查询: 1.mappers文件节选 <resultMap id="AcModelResultMap" type="com.izumi.InstanceModel"> <result column="instanceid" property="instanceID" jdbcType="VARCHAR" /> <result column="insta

随机推荐