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 的值是相同的。

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

接口类:


String querySingleStudent();

List queryAllStudent();
复制代码

Mapper 文件:





复制代码
  1. Map,一般为 hashMap

接口类:


Map queryStudentMap();

List> queryAllStudentMap();
复制代码

Mapper 文件:





复制代码

其中:

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

接口类:


Student querySingleStudentBean();

List queryAllStudentBean();
复制代码

Mapper 文件:





复制代码
  • resultType="student" 为 Student.java 的别名,也可以是全限定名。别名在 mybatis-config.xml 配置文件中设置:
<typeAliases>
    <typeAlias type="com.bean.Student" alias="student"/>
    ...
typeAliases>
复制代码

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

<typeAliases>
    "包名"/>
typeAliases>
复制代码

复杂查询 resultMap

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

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

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

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

"resultMapDemo" type="" autoMapping="true">
    "" column="" jdbcType="VARCHAR" />



复制代码
  1. "queryAllStudent" resultMap="allstudentResultMap"> select SNO,SNAME from test.STUDENT 复制代码

    在标签中

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

    另外需要注意的是这种嵌套查询对于大型结果集和列名并友好,存在 N+1 的问题,因为下一条 SQL 会执行 N 次去循环查询,使用关联查询更合适。再者也可以开启 mybatis 的懒查询功能,嵌套的 SQL 不是一口气顺序执行完,而是在使用的时候才会执行下一条 SQL。例如执行student.getScore().getSNO()才会执行queryScore的 SQL。默认情况下没有开启,需要在配置文件中设置

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

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

    • 嵌套结果集

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

    
    "associationDemoMap" type="student" autoMapping="true">
        "score" javaType="score">
            "SNO" column="SC_SNO"/>
        
    
    
    
    复制代码

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

    "associationDemoMap" type="student" autoMapping="true">
        
        "score" resultMap="anotherMap" columnPrefix="SC_" />
    
    
    
    "anotherMap" type="score" autoMapping="true">
    
    复制代码

    一对多关系

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

    
    private List score;
    public List getScore() {
        return score;
    }
    public void setScore(List score) {
        this.score = score;
    }
    复制代码

    以嵌套结果集为例

    "collectionDemoMap" type="student" autoMapping="true">
        
        "score" ofType="score">
            "SNO" column="SC_SNO"/>
        
    
    
    
    复制代码

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

你可能感兴趣的:(Mybatis 查询语句结果集总结)