Mybatis之@MapKey的实现

 更新时间:2024年09月26日 09:51:59   作者:一只懒鱼a  
本文介绍了Mybatis中@MapKey注解的使用场景与效果,包含使用@MapKey和不使用@MapKey注解的区别,然后通过源码解析产生各种结果的原因,具有一定的参考价值,感兴趣的可以了解一下

前言

演示返回单行、多行数据,使用@MapKey和不使用@MapKey注解的区别,然后通过源码解析产生各种结果的原因

案例演示

分别演示下列四种情况

  • 单行不使用@MapKey注解
  • 多行不使用@MapKey注解
  • 单行使用@MapKey注解
  • 多行使用@MapKey注解

代码准备

创建mybatis-config.xml

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE configuration
        PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
        "http://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration>

    <properties>
        <property name="driver" value="com.mysql.cj.jdbc.Driver"/>
        <property name="url" value="jdbc:mysql://127.0.0.1/test?useUnicode=true&amp;characterEncoding=utf-8&amp;useSSL=false&amp;serverTimezone=Asia/Shanghai&amp;allowPublicKeyRetrieval=true"/>
        <property name="username" value="root"/>
        <property name="password" value="123456"/>
    </properties>

    <settings>
        <setting name="mapUnderscoreToCamelCase" value="true"/>
    </settings>

    <environments default="default">
        <environment id="default">
            <transactionManager type="JDBC"/>
            <dataSource type="POOLED">
                <property name="driver" value="${driver}"/>
                <property name="url" value="${url}"/>
                <property name="username" value="${username}"/>
                <property name="password" value="${password}"/>
            </dataSource>
        </environment>
    </environments>

    <mappers>
        <mapper resource="mapper/MapKeyMapper.xml"/>
    </mappers>

</configuration>

创建MapKeyMapper.xml

<?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">
<mapper namespace="com.ys.mybatis.mapper.MapKeyMapper">

    <select id="getBlogMapById" resultType="map">
         select id, title from blog where id = #{id}
    </select>

    <select id="listBlogMap" resultType="map">
         select id, title from blog
    </select>

</mapper>

创建接口MapKeyMapper

public interface MapKeyMapper {

    Map<String, Object> getBlogMapById(Integer id);

    Map<String, Object> listBlogMap();
}

创建测试类MapKeyTest

@Slf4j
public class MapKeyTest {

    private SqlSessionFactory sqlSessionFactory;

    @BeforeEach
    public void init() {
        InputStream inputStream = ConfigurationTest.class.getClassLoader().getResourceAsStream("mybatis-config.xml");
        sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
    }


    @Test
    public void singleRowTest() {

        SqlSession sqlSession = sqlSessionFactory.openSession();

        MapKeyMapper mapper = sqlSession.getMapper(MapKeyMapper.class);
        Map<String, Object> map = mapper.getBlogMapById(1);
        System.out.println(map);

    }

    @Test
    public void multiLineTest() {

        SqlSession sqlSession = sqlSessionFactory.openSession();

        MapKeyMapper mapper = sqlSession.getMapper(MapKeyMapper.class);
        Map<String, Object> map = mapper.listBlogMap();
        System.out.println(map);
    }


}

单行不使用@MapKey注解

执行测试方法singleRowTest

正确返回,map格式为 Map<String,Object> 

多行不使用@MapKey注解

执行测试方法multiLineTest

异常返回,抛出 TooManyResultsException 

单行使用@MapKey注解

给接口方法添加@MapKey注解

@MapKey("id")
Map<String, Object> getBlogMapById(Integer id);

执行测试方法singleRowTest

 正确返回,map格式为 Map<Long,Map<String,Object>>

多行使用@MapKey注解

给接口方法添加@MapKey注解

@MapKey("id")
Map<String, Object> listBlogMap();

执行测试方法multiLineTest

 正确返回,map格式为 Map<Long, Map<String,Object>>

源码解析

默认情况下,Mybatis会通过MapperMethod的 execute 方法对将要执行的方法进行分发。

MapperMethod结构如下:

public class MapperMethod {

  private final SqlCommand command;
  private final MethodSignature method;

  public MapperMethod(Class<?> mapperInterface, Method method, Configuration config) {
    this.command = new SqlCommand(config, mapperInterface, method);
    this.method = new MethodSignature(config, mapperInterface, method);
  }
}

MapperMethod实例化的过程中,会实例化其内部属性MethodSignature

通过源码我们得出:如果接口方法上存在@MapKey注解,returnsMap 属性就为true  

returnsMap的值决定是执行executeForMap还是selectOne方法

返回类型为map,存在@MapKey注解,执行executeForMap,否则执行selectOne方法

selectOne 

执行selectOne方法,如果返回的条目数大于1,则抛出异常。测试案例2(多行不使用@MapKey注解)就是因为返回的条目数大于1,抛出了TooManyResultsException异常

selectMap

DefaultMapResultHandler实例化

DefaultMapResultHandler实例化的过程中,会实例化其内部属性mappedResults,该属性的类型为Map

handleResult

通过@MapKey指定的key获取value,再以该value为key,原始value为value,put到mappedResults中,最终将这个mappedResults返回。因为原始value的类型是Map<String,Object>,@MapKey指定的key的类型是Long,所以最终返回类型是Map<Long,Map<String,Object>>

到此这篇关于Mybatis之@MapKey的实现的文章就介绍到这了,更多相关Mybatis @MapKey内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • SpringBoot静态资源路径配置及主页显示

    SpringBoot静态资源路径配置及主页显示

    这篇文章主要介绍了SpringBoot静态资源路径配置及主页显示,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下
    2020-04-04
  • SpringBoot使用Caffeine实现缓存的示例代码

    SpringBoot使用Caffeine实现缓存的示例代码

    本文主要介绍了SpringBoot使用Caffeine实现缓存的示例代码,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2022-07-07
  • 浅谈SpringBoot实现自动装配的方法原理

    浅谈SpringBoot实现自动装配的方法原理

    SpringBoot的自动装配是它的一大特点,可以大大提高开发效率,减少重复性代码的编写。本文将详细讲解SpringBoot如何实现自动装配,需要的朋友可以参考下
    2023-05-05
  • Springboot整合hutool验证码的实例代码

    Springboot整合hutool验证码的实例代码

    在 Spring Boot 中,你可以将 Hutool 生成验证码的功能集成到 RESTful API 接口中,这篇文章主要介绍了Springboot整合hutool验证码,需要的朋友可以参考下
    2024-08-08
  • 盘点总结SpringBoot自带工具类使用提升开发效率

    盘点总结SpringBoot自带工具类使用提升开发效率

    这篇文章主要为大家介绍了盘点总结SpringBoot自带工具类使用提升开发效率,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
    2023-12-12
  • IDEA整合Dubbo+Zookeeper+SpringBoot实现

    IDEA整合Dubbo+Zookeeper+SpringBoot实现

    初学者,想自己动手做一个简单的demo,本文主要介绍了IDEA整合Dubbo+Zookeeper+SpringBoot实现,需要的朋友们下面随着小编来一起学习学习吧
    2021-06-06
  • 基于Cookie与Session的Servlet API会话管理操作

    基于Cookie与Session的Servlet API会话管理操作

    这篇文章主要为大家介绍了基于Cookie与Session的Servlet API会话管理操作详解,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
    2022-08-08
  • SpringMVC中的SimpleUrlHandlerMapping用法详解

    SpringMVC中的SimpleUrlHandlerMapping用法详解

    这篇文章主要介绍了SpringMVC中的SimpleUrlHandlerMapping用法详解,SimpleUrlHandlerMapping是Spring MVC中适用性最强的Handler Mapping类,允许明确指定URL模式和Handler的映射关系,有两种方式声明SimpleUrlHandlerMapping,需要的朋友可以参考下
    2023-10-10
  • java追加写入txt文件的方法总结

    java追加写入txt文件的方法总结

    在本篇文章里我们给大家整理了关于java如何追加写入txt文件的方法和代码,需要的朋友们可以参考下。
    2020-02-02
  • Java内存模型final的内存语义

    Java内存模型final的内存语义

    这篇文章主要介绍了Java内存模型final的内存语义,上篇介绍volatile的内存语义,本文讲述的是final的内存语义,相比之下,final域的读和写更像是普通变量的访问。下面我们一起来看看文章学校内容吧,需要的朋友可以参考一下
    2021-11-11

最新评论