最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

MyBatis的MapKey注解實(shí)例解析

 更新時(shí)間:2023年02月08日 11:04:02   作者:念念清晰  
這篇文章主要為大家介紹了MyBatis的MapKey注解實(shí)例解析,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪

使用

mybatis中有很多實(shí)用的注解,但是平時(shí)想不起來使用。今天就來講一下MapKey是如何使用的

說明:本文基于mybatis原生框架3.3.0-SNAPSHOT

一、數(shù)據(jù)準(zhǔn)備

數(shù)據(jù)庫準(zhǔn)備一張user表,插入一點(diǎn)測(cè)試數(shù)據(jù)

CREATE TABLE `user` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `username` varchar(20) DEFAULT NULL,
  `password` varchar(20) DEFAULT NULL,
  `age` int(11) DEFAULT NULL,
  `birthday` varchar(20) DEFAULT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=1018 DEFAULT CHARSET=utf8mb4
select * from user;

二、Mapper配置

UserMapper接口

public interface UserMapper {
    @Select("select * from user limit 1")
    List<User> queryAll1();
    @MapKey("username")
    @Select("select * from user limit 1")
    Map<String, User> queryAll2();
}

這里我們的mapper接口只有兩個(gè)方法queryAll1 queryAll2。這兩個(gè)方法執(zhí)行的SQL是一樣的,SQL的含義也一樣,就是從user表中取出一條數(shù)據(jù)。

不同的是

  • queryAll1 queryAll2的返回值不一樣
  • queryAll1沒有使用MapKey注解,返回值是User對(duì)象,符合SQL返回的只有一條記錄的語義
  • queryAll2使用MapKey注解,但是返回值卻是一個(gè)Map對(duì)象?這似乎不符合SQL返回的語義。SQLselect * from user limit 1只返回一條記錄。怎么返回一個(gè)Map<String, User>對(duì)象呢?這就是MapKey這個(gè)注解的特別之處: 它能夠?qū)⒋娣艑?duì)象的List轉(zhuǎn)化為 key值為對(duì)象的某一屬性的Map。MapKey有一個(gè)屬性value,該屬性值填入的就是對(duì)象的屬性名,作為Map的key值。看不懂這句話沒關(guān)系,看完執(zhí)行結(jié)果回頭再來看就懂了!

三、實(shí)戰(zhàn)

使用mybatis的SqlSession獲取Mapper代理對(duì)象,分別執(zhí)行

@org.junit.Test
public void testMapKey() throws IOException {
    InputStream is = Resources.getResourceAsStream("sqlMapConfig.xml");
    SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(is);
    SqlSession sqlSession = factory.openSession();
    UserMapper userMapper = sqlSession.getMapper(UserMapper.class);
    User users1 = userMapper.queryAll1();
    Map<String, User> users2 = userMapper.queryAll2();
    System.out.println("不使用MapKey查詢: " + users3);
    System.out.println("使用MapKey查詢: " + users4);
}

輸出結(jié)果

不使用MapKey查詢: User{id=1, username='111', password='222', birthday='333'}
使用MapKey查詢: {111=User{id=1, username='111', password='222', birthday='333'}}

可以看到,添加了MapKey注解的方法執(zhí)行結(jié)果Map的key就是注解里value值對(duì)應(yīng)的User對(duì)象的屬性值。value就是SQL查詢得到的結(jié)果User。

這就是MapKey這個(gè)注解的特別之處: 它能夠?qū)⒋娣艑?duì)象的List轉(zhuǎn)化為 key值為對(duì)象的某一屬性的Map。MapKey有一個(gè)屬性value,該屬性值填入的就是對(duì)象的屬性名,作為Map的key值

現(xiàn)在再來看這句話,是不是就能理解了?

實(shí)戰(zhàn)2——注意事項(xiàng)

Mapper接口中的方法標(biāo)注了MapKey后,即使SQL返回多條結(jié)果,最終方法返回的結(jié)果只有一條。這是因?yàn)閡ser表中的username字段全是一樣的。如果把MapKey注解中的value值改為其他user表中不一樣的字段,返回結(jié)果就會(huì)是多條記錄啦

@MapKey("username")
@Select("select * from user limit 10")
Map<String, User> queryAll5();
@MapKey("id")
@Select("select * from user limit 10")
Map<String, User> queryAll6();

執(zhí)行方法

Map<String, User> users5 = userMapper.queryAll5();
System.out.println("users5: " + users5);
Map<String, User> users6 = userMapper.queryAll6();
System.out.println("users6: " + users6);

輸出結(jié)果

users5: {111=User{id=11, username='111', password='222', birthday='333'}}
users6: {1=User{id=1, username='111', password='222', birthday='333'}, 
        3=User{id=3, username='111', password='222', birthday='333'}, 
        4=User{id=4, username='111', password='222', birthday='333'}, 
        5=User{id=5, username='111', password='222', birthday='333'}, 
        6=User{id=6, username='111', password='222', birthday='333'}, 
        7=User{id=7, username='111', password='222', birthday='333'}, 
        8=User{id=8, username='111', password='222', birthday='333'}, 
        9=User{id=9, username='111', password='222', birthday='333'}, 
        10=User{id=10, username='111', password='222', birthday='333'}, 
        11=User{id=11, username='111', password='222', birthday='333'}}

如果標(biāo)注了MapKey,則返回結(jié)果Map的value類型不可以是List,否則執(zhí)行方法會(huì)報(bào)錯(cuò)。下面是錯(cuò)誤示例。

@MapKey("username") // 執(zhí)行會(huì)報(bào)錯(cuò)
@Select("select * from user limit 10")
Map<String, List<User>> queryAll5();

原理

@MapKey("username")
@Select("select * from user limit 10")
Map<String, User> queryAll5();

我們針對(duì)如上這個(gè)方法進(jìn)行分析,在執(zhí)行SQL時(shí)會(huì)調(diào)用SqlSession中的如下代碼

public <K, V> Map<K, V> selectMap(String statement, Object parameter, String mapKey, RowBounds rowBounds) {
  //轉(zhuǎn)而去調(diào)用selectList
  final List<?> list = selectList(statement, parameter, rowBounds);
  final DefaultMapResultHandler<K, V> mapResultHandler = new DefaultMapResultHandler<K, V>(mapKey,
      configuration.getObjectFactory(), configuration.getObjectWrapperFactory());
  final DefaultResultContext context = new DefaultResultContext();
  for (Object o : list) {
    //循環(huán)用DefaultMapResultHandler處理每條記錄
    context.nextResultObject(o);
    mapResultHandler.handleResult(context);
  }
  //注意這個(gè)DefaultMapResultHandler里面存了所有已處理的記錄(內(nèi)部實(shí)現(xiàn)可能就是一個(gè)Map),最后再返回一個(gè)Map
  return mapResultHandler.getMappedResults();
}

來分析源碼

  • 使用Executor查詢結(jié)果,這里的SQL是select * from user limit 10,SQL執(zhí)行的結(jié)果返回給List對(duì)象,List中確實(shí)有10條記錄
  • 構(gòu)造一個(gè)對(duì)象DefaultMapResultHandler mapResultHandler,它是用來處理結(jié)果集的映射的,
  • 遍歷第一步中List得到的結(jié)果集對(duì)象

調(diào)用mapResultHandler.handleResult(context);方法將List結(jié)果集中每一條記錄對(duì)應(yīng)Mapkey中的屬性值取出,作為Map的key加入到集合里。handleResult源碼如下。其中主要關(guān)注這一行就可以了mappedResults.put(key, value);

@Override
public void handleResult(ResultContext context) {
  // TODO is that assignment always true?
  //得到一條記錄
  //這邊黃色警告沒法去掉了?因?yàn)榉祷豋bject型
  final V value = (V) context.getResultObject();
  //MetaObject.forObject,包裝一下記錄
  //MetaObject是用反射來包裝各種類型
  final MetaObject mo = MetaObject.forObject(value, objectFactory, objectWrapperFactory);
  final K key = (K) mo.getValue(mapKey);
  mappedResults.put(key, value);
  //這個(gè)類主要目的是把得到的List轉(zhuǎn)為Map
}

通過handleResult方法源碼可以看到,對(duì)于List結(jié)果集中的一條記錄,取出屬性u(píng)sername的值作為Map的key值添加到mappedResults集合中。那么如果key值相同就會(huì)被覆蓋!這就是實(shí)戰(zhàn)篇坑1的原理

最后是通過mapResultHandler.getMappedResults();方法返回第4步中的map最為最終方法的返回值。

總結(jié)

MapKey的作用:它能夠?qū)⒋娣艑?duì)象的List轉(zhuǎn)化為 key值為對(duì)象的某一屬性的Map。MapKey有一個(gè)屬性value,該屬性值填入的就是對(duì)象的屬性名,作為Map的key值

使用場(chǎng)景:可以針對(duì)結(jié)果集中的某個(gè)屬性去重,而不在乎其他字段是否重復(fù)

以上就是MyBatis的MapKey注解實(shí)例解析的詳細(xì)內(nèi)容,更多關(guān)于MyBatis MapKey注解的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!

相關(guān)文章

  • JAVA錯(cuò)誤:'無效目標(biāo)發(fā)行版?17'的解決方案

    JAVA錯(cuò)誤:'無效目標(biāo)發(fā)行版?17'的解決方案

    這篇文章主要給大家介紹了關(guān)于JAVA錯(cuò)誤:'無效目標(biāo)發(fā)行版?17'的解決方案,文中通過圖文介紹的非常詳細(xì),對(duì)大家學(xué)習(xí)或使用java具有一的的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下
    2022-09-09
  • 淺談對(duì)象與Map相互轉(zhuǎn)化

    淺談對(duì)象與Map相互轉(zhuǎn)化

    這篇文章主要介紹了利用BeanMap進(jìn)行對(duì)象與Map的相互轉(zhuǎn)換,在文中列舉了完整代碼,需要的朋友可以參考下。
    2017-09-09
  • springcloud整合gateway實(shí)現(xiàn)網(wǎng)關(guān)全局過濾器功能

    springcloud整合gateway實(shí)現(xiàn)網(wǎng)關(guān)全局過濾器功能

    本文主要介紹了springcloud整合gateway實(shí)現(xiàn)網(wǎng)關(guān)全局過濾器功能,文中通過示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2022-02-02
  • Java橋接模式原理及用法解析

    Java橋接模式原理及用法解析

    這篇文章主要介紹了Java橋接模式原理及用法解析,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下
    2020-05-05
  • Java中使用opencv的問題

    Java中使用opencv的問題

    這篇文章主要介紹了Java中使用opencv的問題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2023-10-10
  • Spring?Data默認(rèn)值的錯(cuò)誤解決

    Spring?Data默認(rèn)值的錯(cuò)誤解決

    本文主要介紹了Spring?Data默認(rèn)值的錯(cuò)誤解決,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2023-01-01
  • Mybatis之foreach標(biāo)簽內(nèi)傳入list為空的問題

    Mybatis之foreach標(biāo)簽內(nèi)傳入list為空的問題

    這篇文章主要介紹了Mybatis之foreach標(biāo)簽內(nèi)傳入list為空的問題及解決方案,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2024-03-03
  • springmvc json類型轉(zhuǎn)換錯(cuò)誤解決方案

    springmvc json類型轉(zhuǎn)換錯(cuò)誤解決方案

    這篇文章主要介紹了springmvc json類型轉(zhuǎn)換錯(cuò)誤解決方案,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下
    2019-12-12
  • java中如何執(zhí)行xshell命令

    java中如何執(zhí)行xshell命令

    這篇文章主要介紹了java中如何執(zhí)行xshell命令,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2022-06-06
  • logback高效狀態(tài)管理器StatusManager源碼解析

    logback高效狀態(tài)管理器StatusManager源碼解析

    這篇文章主要為大家介紹了logback高效狀態(tài)管理器StatusManager源碼解析,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2023-11-11

最新評(píng)論

贺州市| 大荔县| 肥乡县| 桐乡市| 山东省| 东城区| 苍南县| 纳雍县| 镇沅| 和林格尔县| 昭觉县| 平泉县| 丹阳市| 遂川县| 丹巴县| 林芝县| 务川| 韶关市| 敖汉旗| 孙吴县| 洞头县| 乐清市| 定南县| 肇庆市| 徐州市| 镇赉县| 云和县| 准格尔旗| 宁安市| 东辽县| 军事| 井冈山市| 安溪县| 偏关县| 麦盖提县| 饶河县| 达尔| 建平县| 青海省| 灵川县| 集安市|