Mybatis之@MapKey的實(shí)現(xiàn)
前言
演示返回單行、多行數(shù)據(jù),使用@MapKey和不使用@MapKey注解的區(qū)別,然后通過源碼解析產(chǎn)生各種結(jié)果的原因
案例演示
分別演示下列四種情況
- 單行不使用@MapKey注解
- 多行不使用@MapKey注解
- 單行使用@MapKey注解
- 多行使用@MapKey注解
代碼準(zhǔn)備
創(chuàng)建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&characterEncoding=utf-8&useSSL=false&serverTimezone=Asia/Shanghai&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>
創(chuàng)建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>
創(chuàng)建接口MapKeyMapper
public interface MapKeyMapper { Map<String, Object> getBlogMapById(Integer id); Map<String, Object> listBlogMap(); }
創(chuàng)建測(cè)試類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注解
執(zhí)行測(cè)試方法singleRowTest
正確返回,map格式為 Map<String,Object>
多行不使用@MapKey注解
執(zhí)行測(cè)試方法multiLineTest
異常返回,拋出 TooManyResultsException
單行使用@MapKey注解
給接口方法添加@MapKey注解
@MapKey("id") Map<String, Object> getBlogMapById(Integer id);
執(zhí)行測(cè)試方法singleRowTest
正確返回,map格式為 Map<Long,Map<String,Object>>
多行使用@MapKey注解
給接口方法添加@MapKey注解
@MapKey("id") Map<String, Object> listBlogMap();
執(zhí)行測(cè)試方法multiLineTest
正確返回,map格式為 Map<Long, Map<String,Object>>
源碼解析
默認(rèn)情況下,Mybatis會(huì)通過MapperMethod的 execute 方法對(duì)將要執(zhí)行的方法進(jìn)行分發(fā)。
MapperMethod結(jié)構(gòu)如下:
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實(shí)例化的過程中,會(huì)實(shí)例化其內(nèi)部屬性MethodSignature
通過源碼我們得出:如果接口方法上存在@MapKey注解,returnsMap 屬性就為true
returnsMap的值決定是執(zhí)行executeForMap還是selectOne方法
返回類型為map,存在@MapKey注解,執(zhí)行executeForMap,否則執(zhí)行selectOne方法
selectOne
執(zhí)行selectOne方法,如果返回的條目數(shù)大于1,則拋出異常。測(cè)試案例2(多行不使用@MapKey注解)就是因?yàn)榉祷氐臈l目數(shù)大于1,拋出了TooManyResultsException異常
selectMap
DefaultMapResultHandler實(shí)例化
DefaultMapResultHandler實(shí)例化的過程中,會(huì)實(shí)例化其內(nèi)部屬性mappedResults,該屬性的類型為Map
handleResult
通過@MapKey指定的key獲取value,再以該value為key,原始value為value,put到mappedResults中,最終將這個(gè)mappedResults返回。因?yàn)樵紇alue的類型是Map<String,Object>,@MapKey指定的key的類型是Long,所以最終返回類型是Map<Long,Map<String,Object>>
到此這篇關(guān)于Mybatis之@MapKey的實(shí)現(xiàn)的文章就介紹到這了,更多相關(guān)Mybatis @MapKey內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
SpringBoot使用Caffeine實(shí)現(xiàn)緩存的示例代碼
本文主要介紹了SpringBoot使用Caffeine實(shí)現(xiàn)緩存的示例代碼,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2022-07-07淺談SpringBoot實(shí)現(xiàn)自動(dòng)裝配的方法原理
SpringBoot的自動(dòng)裝配是它的一大特點(diǎn),可以大大提高開發(fā)效率,減少重復(fù)性代碼的編寫。本文將詳細(xì)講解SpringBoot如何實(shí)現(xiàn)自動(dòng)裝配,需要的朋友可以參考下2023-05-05Springboot整合hutool驗(yàn)證碼的實(shí)例代碼
在 Spring Boot 中,你可以將 Hutool 生成驗(yàn)證碼的功能集成到 RESTful API 接口中,這篇文章主要介紹了Springboot整合hutool驗(yàn)證碼,需要的朋友可以參考下2024-08-08盤點(diǎn)總結(jié)SpringBoot自帶工具類使用提升開發(fā)效率
這篇文章主要為大家介紹了盤點(diǎn)總結(jié)SpringBoot自帶工具類使用提升開發(fā)效率,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2023-12-12IDEA整合Dubbo+Zookeeper+SpringBoot實(shí)現(xiàn)
初學(xué)者,想自己動(dòng)手做一個(gè)簡(jiǎn)單的demo,本文主要介紹了IDEA整合Dubbo+Zookeeper+SpringBoot實(shí)現(xiàn),需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2021-06-06基于Cookie與Session的Servlet?API會(huì)話管理操作
這篇文章主要為大家介紹了基于Cookie與Session的Servlet?API會(huì)話管理操作詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2022-08-08SpringMVC中的SimpleUrlHandlerMapping用法詳解
這篇文章主要介紹了SpringMVC中的SimpleUrlHandlerMapping用法詳解,SimpleUrlHandlerMapping是Spring MVC中適用性最強(qiáng)的Handler Mapping類,允許明確指定URL模式和Handler的映射關(guān)系,有兩種方式聲明SimpleUrlHandlerMapping,需要的朋友可以參考下2023-10-10