详解MyBatis resultType与resultMap中的几种返回类型

目录
  • 一、返回集合
    • 1.返回JavaBean集合
    • 2.返回 Map 集合
  • 二、返回 Map
    • 1.一条记录
    • 2.多条记录,需要指定 Map 的 Key 和 Value 的类型
  • 三、返回 resultMap 自定义结果集封装
    • 1.自定义 JavaBean 的封装
    • 2.关联查询的封装,一对一,JavaBean 属性包含 JavaBean
    • 3.关联查询的封装,一对多,JavaBean 属性包含 JavaBean 的集合
    • 4.鉴别器discriminator

一、返回集合

1.返回JavaBean集合

public List<MyUser> selectMyUserByNameLike(String name);
<!-- resultType 集合内的元素类型 -->
<select id="selectMyUserByNameLike" resultType="myUser" parameterType="string">
  select * from myuser where name like #{name}
</select>

测试方法

public static void main(String[] args) {
    SqlSession session = null;
    try {
        InputStream inputStream = Resources.getResourceAsStream("mybatis-config.xml");
        SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
        session = sqlSessionFactory.openSession();

        MyUserMapper mapper = session.getMapper(MyUserMapper.class);
        List<MyUser> myUsers = mapper.selectMyUserByNameLike("%a%");
        System.out.println(myUsers);
    } catch (IOException e) {
        e.printStackTrace();
    } finally {
        if (session != null) {
            session.close();
        }
    }
}

2.返回 Map 集合

<!--public List<Map<String,Object>> getMyUser()-->
<select id="getMyUser" resultType="map">
  select * from myuser
</select>

二、返回 Map

1.一条记录

public Map<String,Object> selectMyUserById(Integer id);
<select id="selectMyUserById" resultType="map" parameterType="integer">
  select * from myuser where id = #{id}
</select>

2.多条记录,需要指定 Map 的 Key 和 Value 的类型

// 指定 Map 的 Key 从记录中的 id 列获取
@MapKey("id")
public Map<String,MyUser> selectMyUserByGtId(Integer id);
<!-- resultType Map 中 value 的类型 -->
<select id="selectMyUserByGtId" resultType="myUser" parameterType="integer">
  select * from myuser where id > #{id}
</select>

三、返回 resultMap 自定义结果集封装

关于自动映射封装的配置

<settings>
    <!-- 自动映射有三种模式,NONE、PARTIAL、FULL。NONE 不启用自动映射,PARTIAL 只对非嵌套的 resultMap 进行自动映射,FULL 表示对所有的 resultMap 都进行自动映射。默认为 PARTIAL -->
    <setting name="autoMappingBehavior" value="PARTIAL"/>
    <!-- 数据库字段下划线转Bean字段的驼峰命名 -->
    <setting name="mapUnderscoreToCamelCase" value="true"/>
    <!-- 控制台打印SQL -->
    <setting name="logImpl" value="STDOUT_LOGGING" />
</settings>

默认数据库字段与 JavaBean 对应不上时可开启驼峰命名或查询时使用别名http://www.mybatis.org/mybatis-3/zh/sqlmap-xml.html

1.自定义 JavaBean 的封装

确认是否成功可以关掉 MyBatis 的自动映射

<setting name="autoMappingBehavior" value="NONE"/>
public MyUser selectMyUserById(Integer id);
<!-- 自定义某个 javaBean 的封装规则
    type:自定义规则中JavaBean类型的全路径,可用别名
    id:唯一id方便引用 -->
<resultMap type="myUser" id="myUserResultMap">
    <!-- 指定主键列的封装规则,用 id 标签定义主键会底层有优化
    column:指定哪一列
    property:指定对应的javaBean属性 -->
    <id column="id" property="id"/>
    <!-- 定义普通列封装规则 -->
    <result column="name" property="name"/>
    <!-- 其他不指定的列会自动封装:建议只要写 resultMap 就把全部的映射规则都写上 -->
    <result column="age" property="age"/>
</resultMap>

<!-- 使用 resultMap,不使用 resultType -->
<select id="selectMyUserById" resultMap="myUserResultMap" parameterType="integer">
  select * from myuser where id = #{id}
</select>

2.关联查询的封装,一对一,JavaBean 属性包含 JavaBean

public MyUser selectMyUserById(Integer id);

直接调用属性赋值

<resultMap type="myUser" id="myUserResultMap">
    <id column="id" property="id"/>
    <result column="name" property="name"/>
    <result column="age" property="age"/>
    <!--直接属性封装-->
    <result column="did" property="dept.id"/>
    <result column="dname" property="dept.name"/>
</resultMap>

<select id="selectMyUserById" resultMap="myUserResultMap" parameterType="integer">
  SELECT m.id, m.name, m.age, m.did, d.name AS dname FROM myuser m,dept d WHERE m.did = d.id AND m.id = #{id}
</select>

使用association

<resultMap type="com.bean.MyUser" id="myUserResultMap">
    <id column="id" property="id"/>
    <result column="name" property="name"/>
    <result column="age" property="age"/>
    <!--  association 指定联合的 javaBean 对象
        property="dept":指定哪个属性是联合的对象
        javaType:指定这个属性对象的类型[不能省略] -->
    <association property="dept" javaType="com.bean.Dept">
        <id column="did" property="id"/>
        <result column="dname" property="name"/>
    </association>
</resultMap>

<select id="selectMyUserById" resultMap="myUserResultMap" parameterType="integer">
  SELECT m.id, m.name, m.age, m.did, d.name AS dname FROM myuser m,dept d WHERE m.did = d.id AND m.id = #{id}
</select>

使用association 二次查询,即有两条 SQL

<resultMap id="myUserResultMap" type="com.bean.MyUser">
    <id column="id" property="id"/>
    <result column="name" property="name"/>
    <result column="age" property="age"/>
    <!-- association 定义关联对象的封装规则
        select:当前属性是调用 select 指定的方法查出的结果
        column:将哪一列的值传给这个方法 -->
    <association property="dept" select="com.dao.DeptMapper.selectDeptById" column="did"/>
</resultMap>
<select id="selectMyUserById" resultMap="myUserResultMap" parameterType="integer">
  SELECT * FROM myuser WHERE id = #{id}
</select>
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
        PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
        "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<!-- namespace 对应接口文件的全路径 -->
<mapper namespace="com.dao.DeptMapper">
    <select id="selectDeptById" resultType="dept" parameterType="string">
      select * from dept where id = #{id}
    </select>
</mapper>

开启懒加载:在没有使用 Dept 的属性时,则只会加载 MyUser 的属性。即只会发送一条 SQL 语句,要使用Dept 属性时才会发送第二条 SQL。不会一次性发送两条 SQL

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

3.关联查询的封装,一对多,JavaBean 属性包含 JavaBean 的集合

使用association

public Dept getDeptById(Integer id);
<resultMap type="com.bean.Dept" id="MyDept">
    <id column="did" property="id"/>
    <result column="dname" property="name"/>
    <!-- collection 定义关联集合类型的属性封装规则
        ofType 指定集合里面元素的类型 -->
    <collection property="myUsers" ofType="com.bean.MyUser">
        <!-- 定义集合中元素的封装规则 -->
        <id column="id" property="id"/>
        <result column="name" property="name"/>
        <result column="age" property="age"/>
    </collection>
</resultMap>
<select id="getDeptById" resultMap="MyDept">
    SELECT m.id,m.name,m.age,m.did,d.name AS dname FROM myuser m,dept d WHERE m.did = d.id AND d.id = #{id}
</select>

关闭懒加载,使用二次查询

public Dept getDeptByIdStep(Integer did);
<!-- Collection 分段查询 -->
<resultMap type="com.bean.Dept" id="MyDeptStep">
    <id column="id" property="id"/>
    <result column="name" property="name"/>
    <collection property="myUsers" select="com.dao.MyUserMapper.selectMyUserByDid"
                column="{did=id}" fetchType="eager"/>
    <!-- column 要处理复合主键或传递多个值过去:可以将多列的值封装 Map 传递,指定多个列名通过 column="{prop1=col1,prop2=col2}"
        语法来传递给嵌套查询语句。这会引起 prop1 和 prop2 以参数对象形式来设置给目标嵌套查询语句
        fetchType="lazy":是否延迟加载,优先级高于全局配置,lazy:延迟,eager:立即 -->
</resultMap>
<select id="getDeptByIdStep" resultMap="MyDeptStep">
    select * from dept where id = #{id}
</select>
public List<MyUser> selectMyUserByDid(Integer dId);
<select id="selectMyUserByDid" resultType="myUser">
  select * from myuser where dId = #{did}
</select>

4.鉴别器discriminator

<!--public MyUser selectMyUserById(Integer id);-->
<select id="selectMyUserById" resultMap="MyEmpDis" parameterType="integer">
  SELECT * FROM myuser WHERE id = #{id}
</select>
<resultMap id="MyEmpDis" type="com.bean.MyUser">
    <id column="id" property="id"/>
    <result column="name" property="name"/>
    <result column="age" property="age"/>
    <!-- column:指定判定的列名 javaType:列值对应的java类型  -->
    <discriminator javaType="integer" column="age">
        <!-- 21岁 封装课程至 JavaBean -->
        <case value="21" resultType="com.bean.MyUser">
            <association property="dept" select="com.dao.DeptMapper.selectDeptById" column="did"/>
        </case>
        <!-- 33岁 不封装课程至 JavaBean 且把 age 赋值给 id -->
        <case value="33" resultType="com.bean.MyUser">
            <result column="age" property="id"/>
        </case>
    </discriminator>
</resultMap>
<!--public Dept selectDeptById(Integer id);-->
<select id="selectDeptById" resultType="dept" parameterType="string">
  select * from dept where id = #{id}
</select>

上面测试中使用的实体类与数据

public class Dept {
    private Integer id;
    private String name;
    private List<MyUser> myUsers;
public class MyUser {
    private Integer id;
    private String name;
    private Integer age;
    private Dept dept;

https://mybatis.org/mybatis-3/zh/sqlmap-xml.html

到此这篇关于详解MyBatis resultType与resultMap中的几种返回类型的文章就介绍到这了,更多相关MyBatis resultType与resultMap返回类型内容请搜索我们以前的文章或继续浏览下面的相关文章希望大家以后多多支持我们!

时间: 2021-09-14

Mybatis中的resultType和resultMap查询操作实例详解

resultType和resultMap只能有一个成立,resultType是直接表示返回类型的,而resultMap则是对外部ResultMap的引用,resultMap解决复杂查询是的映射问题.比如:列名和对象属性名不一致时可以使用resultMap来配置:还有查询的对象中包含其他的对象等. MyBatisConfig.xml <?xml version="1.0" encoding="UTF-8" ?> <!DOCTYPE configura

MyBatis中关于resultType和resultMap的区别介绍

MyBatis中在查询进行select映射的时候,返回类型可以用resultType,也可以用resultMap,resultType是直接表示返回类型的(对应着我们的model对象中的实体),而resultMap则是对外部ResultMap的引用(提前定义了db和model之间的隐射key-->value关系),但是resultType跟resultMap不能同时存在. 在MyBatis进行查询映射时,其实查询出来的每一个属性都是放在一个对应的Map里面的,其中键是属性名,值则是其对应的值.

深入理解Mybatis中的resultType和resultMap

 一.概述 MyBatis中在查询进行select映射的时候,返回类型可以用resultType,也可以用resultMap,resultType是直接表示返回类型的,而resultMap则是对外部ResultMap的引用,但是resultType跟resultMap不能同时存在. 在MyBatis进行查询映射时,其实查询出来的每一个属性都是放在一个对应的Map里面的,其中键是属性名,值则是其对应的值. ①当提供的返回类型属性是resultType时,MyBatis会将Map里面的键值对取出赋给

MyBatis中resultMap和resultType的区别详解

总结 基本映射 :(resultType)使用resultType进行输出映射,只有查询出来的列名和pojo中的属性名一致,该列才可以映射成功.(数据库,实体,查询字段,这些全部都得一一对应)高级映射 :(resultMap) 如果查询出来的列名和pojo的属性名不一致,通过定义一个resultMap对列名和pojo属性名之间作一个映射关系.(高级映射,字段名称可以不一致,通过映射来实现 resultType和resultMap功能类似 ,都是返回对象信息 ,但是resultMap要更强大一些

Mybatis中Collection集合标签的使用详解

mybatis简单的CURD就不用多说了,网上相关博客文档一大堆.分析一下Mybatis里面的collection聚集查询. 假设一个班级有多名学生为例,通过班级号查询出该班级的信息,和班级里面的所有学生的信息,一般的做法就是通过班级号把班级的信息查询出来,再通过班级ID号把该班级里面的所有学生查询出来,我们不用这种通用的方法 1.班级实体类可以定义为这样: import java.util.List; public class ClazzEntity { private int clazzID

基于python中staticmethod和classmethod的区别(详解)

例子 class A(object): def foo(self,x): print "executing foo(%s,%s)"%(self,x) @classmethod def class_foo(cls,x): print "executing class_foo(%s,%s)"%(cls,x) @staticmethod def static_foo(x): print "executing static_foo(%s)"%x a=A(

node.js中grunt和gulp的区别详解

node.js中grunt和gulp的区别详解 自nodeJS登上前端舞台,自动化构建变得越来越流行.目前最流行的当属grunt和gulp,这两个光看名字挺像,功能也差不多,不过gulp能在grunt这位大哥如日中天的境况下开辟出自己的一片天地,有着她独到的优点. 易用 Gulp相比Grunt更简洁,而且遵循代码优于配置策略,维护Gulp更像是写代码. 高效 Gulp相比Grunt更有设计感,核心设计基于Unix流的概念,通过管道连接,不需要写中间文件. 高质量 Gulp的每个插件只完成一个功能

基于js中this和event 的区别(详解)

今天在看javascript入门经典-事件一章中看到了 this 和 event 两种传参形式.因为作为一个初级的前端开发人员平时只用过 this传参,so很想弄清楚,this和event的区别是什么,什么情况下用什么比较合适. onclick = changeImg(this)       vs     onclick = changeImg(event) <img src='usa.gif' onclick="changeImg(event)" /> <scrip

iOS中setValue和setObject的区别详解

网上关于setValue和setObject的区别的文章很多,说的并不准确,首先我们得知道: setObject:ForKey: 是NSMutableDictionary特有的:setValue:ForKey:是KVC的主要方法 话不多说,上代码: - (void)viewDidLoad { [super viewDidLoad]; //setObject和setvalue的区别 NSMutableDictionary *dic = [NSMutableDictionary dictionary

python中import reload __import__的区别详解

import 作用:导入/引入一个python标准模块,其中包括.py文件.带有__init__.py文件的目录(自定义模块). import module_name[,module1,...] from module import *|child[,child1,...] 注意:多次重复使用import语句时,不会重新加载被指定的模块,只是把对该模块的内存地址给引用到本地变量环境. 实例: pythontab.py #!/usr/bin/env python #encoding: utf-8

JavaScript中object和Object的区别(详解)

JavaScript中object和Object有什么区别,为什么用typeof检测对象,返回object,而用instanceof 必须要接Object呢 这个问题和我之前遇到的问题非常相似,我认为这里有两个问题需要解决,一个是运算符new的作用机制,一个是function关键字和Funtion内置对象之间的区别.看了一些前辈的博客和标准,这里帮提问者总结一下. 1.new new运算符的作用是创建一个对象实例.这个对象可以是用户自定义的,也可以是带构造函数的一些系统自带的对象.如果 new

Android中asset和raw的区别详解

*res/raw和assets的相同点: 1.两者目录下的文件在打包后会原封不动的保存在apk包中,不会被编译成二进制. *res/raw和assets的不同点: 1.res/raw中的文件会被映射到R.java文件中,访问的时候直接使用资源ID即R.id.filename:assets文件夹下的文件不会被映射到 R.java中,访问的时候需要AssetManager类. 2.res/raw不可以有目录结构,而assets则可以有目录结构,也就是assets目录下可以再建立文件夹 *读取文件资源

基于Java中throw和throws的区别(详解)

系统自动抛出的异常 所有系统定义的编译和运行异常都可以由系统自动抛出,称为标准异常,并且 Java 强烈地要求应用程序进行完整的异常处理,给用户友好的提示,或者修正后使程序继续执行. 语句抛出的异常 用户程序自定义的异常和应用程序特定的异常,必须借助于 throws 和 throw 语句来定义抛出异常. throw是语句抛出一个异常. 语法:throw (异常对象); throw e; throws是方法可能抛出异常的声明.(用在声明方法时,表示该方法可能要抛出异常) 语法:[(修饰符)](返回