MyBatis查询两个字段,返回Map,一个字段作为key,一个字段作为value的实现

news2024/11/24 9:39:27

项目场景:

  在使用MyBatis,我们经常会遇到这种情况:SELECT两个字段,需要返回一个Map,其中第一个字段作为key,第二个字段作为value。MyBatis的MapKey虽然很实用,但并不能解决这种场景。


问题描述

第一种情况

我们查询出id和name两个字段,想用Map来接收它,然后想着直接MyBatis直接返回Map对象就好了

Mapper:

这种情况结果只能一条记录,多条记录会报错:nested exception is org.apache.ibatis.exceptions.TooManyResultsException: Expected one result (or null) to be returned by selectOne(), but found: 3

/**
 * 结果只能一条记录,多条记录会报错
 */
@Select("select id, name from t_test where id = 1")
Map<String, Object> selectOne();

Service测试: 

@Service
public class TestService{

    @Autowired
    private TestMapper testMapper;

    public void selectOne() {
        Map<String, Object> map = testMapper.selectOne();
        for (Map.Entry<String, Object> entry : map.entrySet()) {
            System.out.println("key:"+entry.getKey()+",value:"+entry.getValue());
        }
    }
}

 打印的结果:

key:name,value:张三
key:id,value:1

发现打印的结果跟想的不一样 ,想的结果是key:1,value:张三,因为MyBatis是把结果以("id":1)、("name":"张三")的形式保存在Map中的。


第二种情况

然后使用@MapKey改进

Mapper:

这样就可以接收多条记录了

/**
     * Map接收多条记录
     */
    @Select("select id, name from t_test")
    @MapKey("id")   //指定key
    Map<Integer, Map<String, Object>> tooMany();

Service测试:  

@Service
public class TestService{

    @Autowired
    private TestMapper testMapper;

    public void tooMany() {
        Map<Integer, Map<String, Object>> map = testMapper.tooMany();
        for (Map.Entry<Integer, Map<String, Object>> entry : map.entrySet()) {
            System.out.println("key:"+entry.getKey()+",value:"+entry.getValue());
        }
        
    }
}

 打印的结果:

key:1,value:{name=张三, id=1}
key:2,value:{name=李四, id=2}
key:3,value:{name=王五, id=3}

 数据是都能正常获取了,可还不是想要的格式,想的结果是key:1,value:张三。


解决方案:

如果要实现id字段作为key,name字段作为value,可以使用mybatis提供的ResultHandler的结果处理器,他能感知到你的每条数据(可以当做limit 1来理解),拿到该条数据你加工下,继续拿下一条数据,有点类似于for循环,每次拿到数据放到map中,最后拿到这个map。

1.xml

首先xml写好sql,@select注解也可以,但是没有xml方便,因为需要返回resultMap

<?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.test.dao.TestMapper">

    <!--这里key-value报红不影响-->
    <resultMap id="mapResult" type="map">
        <result property="key" column="id"/>
        <result property="value" column="name"/>
    </resultMap>

    <select id="resultHandler" resultMap="mapResult">
        select id, name from t_test
    </select>

</mapper>

这里大家会发现key和value会报红,其实不影响,如果实在觉得不舒服,那么可以把result这两行注释掉变成:

<resultMap id="mapResult" type="map">
	<!--<result property="key" column="id"/>-->
	<!--<result property="value" column="name"/>-->
</resultMap>

 但是这样的话,后面map获取值就要改成:map.get("id"), map.get("name"),就不能兼容其它的表使用。

2.Mapper

返回值必须为void,有其它参数可以加在mapResultHandler参数之前比如:

resultHandler(Integer id, MapResultHandler<Integer, String> mapResultHandler)

/**
     * 使用ResultHandler实现key-value接收多条记录
     * 返回值必须为void,有其它参数可以加在mapResultHandler参数之前比如:
     * resultHandler(Integer id, MapResultHandler<Integer, String> mapResultHandler)
     */
    void resultHandler(MapResultHandler<Integer, String> mapResultHandler);

3.ResultHandle

对应xml配置的key-value

public class MapResultHandler<K,V> implements ResultHandler<Map<K,V>> {
    private final Map<K,V> mappedResults = new HashMap<>();

    @Override
    public void handleResult(ResultContext context) {
        Map map = (Map) context.getResultObject();
        mappedResults.put((K)map.get("key"), (V)map.get("value"));
    }

    public Map<K,V> getMappedResults() {
        return mappedResults;
    }
}

 4.Service测试:  

@Service
public class TestService{

    @Autowired
    private TestMapper testMapper;

    public void resultHandler() {
        MapResultHandler<Integer, String> resultHandler = new MapResultHandler<>();
        testMapper.resultHandler(resultHandler);
        Map<Integer, String> map = resultHandler.getMappedResults();
        for (Map.Entry<Integer, String> entry : map.entrySet()) {
            System.out.println("key:"+entry.getKey()+",value:"+entry.getValue());
        }
        
    }
}

5.打印结果:

key:1,value:张三
key:2,value:李四
key:3,value:王五

达到了想要的效果,但是代码量也增加了,为了实现key-value牺牲太大。


备用方案:

使用ResultHandler的解决方案比较麻烦,还是使用@MapKey比较方便,就是获取value的时候再多一步,除了使用Map接收,还可以使用实体类接收。

1.创建实体类

// User实体类
public class User {
    private Integer id;
    private String name;
    // 省略getter和setter方法
}

2.Mapper

/**
 * 实体类接收多条记录
 */
@Select("select id, name from t_test")
@MapKey("id")   //指定key
Map<Integer, User> getUser();

3. Service测试:  

@Service
public class TestService{

    @Autowired
    private TestMapper testMapper;

    public void getUser() {
        Map<Integer, User> map = testMapper.getUser();
        for (Map.Entry<Integer, User> entry : map.entrySet()) {
            System.out.println("key:"+entry.getKey()+",value:"+entry.getValue());
        }
        
    }
}

 4.打印结果:

key:1,value:User(id=1, name=张三)
key:2,value:User(id=2, name=李四)
key:3,value:User(id=3, name=王五)

总结 

  1. Map<String, Object>只能接收单条数据。
  2. @MapKey指定key,可以接受多条数据,会把查询得到的每一行数据封装成一个Map(key=id,value=Map),然后把所有的Map又以字段名为key,都封装进一个Map或者实体类中。
  3. ResultHandle可以实现一个字段作为key,一个字段作为value的效果,但是比较麻烦些。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1831504.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

vue分类

先看效果 再看代码 <category-tab v-model"params.area" name"地区" :list"areaList" /><category-tab v-model"params.type" name"类型" :list"typeList" /><category-tab v-model"params.…

WPF/C#:如何将数据分组显示

WPF Samples中的示例 在WPF Samples中有一个关于Grouping的Demo。 该Demo结构如下&#xff1a; MainWindow.xaml如下&#xff1a; <Window x:Class"Grouping.MainWindow"xmlns"http://schemas.microsoft.com/winfx/2006/xaml/presentation"xmlns:x&q…

【面试 - 页面优化举例】页面跳转卡顿问题解决 - 页面跳转速度优化

目录 为何要优化如何优化优化1 - 懒加载优化2 - el-tree 子节点默认不展开 为何要优化 页面A跳转到也页面B时&#xff0c;页面出现卡顿情况&#xff1a; 【问题】页面A → 页面B时&#xff0c;页面B进入到了 created 钩子后过了六七秒才进入到 mounted 钩子&#xff1b;【分析经…

vue分页

先看效果 再看代码 <!-- 分页 --><div v-if"pageParams.pageCount > 1" class"flex justify-end mt-6"><n-paginationv-model:page"pageParams.page" v-model:page-size"pageParams.pageSize" :page-count"pa…

生产 的mybatisplus 日志输入到日志文件

默认是输出到控制台.不输出到日志文件 输出到日志文件.需要修改配置 第一步. logging:config: classpath:logback-wshoto.xml第二步 mybatis-plus:configuration:cache-enabled: truedefault-executor-type: reuselog-impl: org.apache.ibatis.logging.slf4j.Slf4jImpl第三步…

标准立项 | 膜曝气生物膜反应器(MABR)平板曝气膜

立项单位&#xff1a;天津市华宇膜技术有限公司、中国市政工程中南设计研究总院有限公司、中建生态环境集团有限公司、富朗世水务技术(江苏)有限公司、常州宣清环境科技有限公司 膜组件开发 膜腔内部支撑结构-一在膜腔内部设置支撑结构以防止膜腔在水压下压实&#xff0c;同时…

CRMEB多门店的门店后台首页路由

如何在输入 http://localhost:8080/、http://localhost:8080/store/、http://localhost:8080/custom-store/ 这三个中任意一个链接都能正确跳转到 http://localhost:8080/store/home/index 。要实这个要求&#xff0c;有两种方式&#xff1a; 重定向 const router new VueRo…

WPF/C#:更改界面的样式

项目结构&#xff1a; 先来看看BlueSkin.xaml与YellowSkin.xaml。 BlueSkin.xaml&#xff1a; <ResourceDictionaryxmlns"http://schemas.microsoft.com/winfx/2006/xaml/presentation"xmlns:x"http://schemas.microsoft.com/winfx/2006/xaml"xmlns:l…

SVN代码无法提交(报错lock)

SVN无法commit(可以导出可以update)报错画面如下&#xff1a; 报错&#xff1a;If you want to break the lock, use the check For Modifcations dialoo or the repository browser. 前提&#xff1a;使用解锁和clean up无效 解决办法&#xff1a;导出报错仓库数据到本地&am…

9种编程语言的对比分析

在当今的软件开发领域&#xff0c;编程语言扮演着至关重要的角色。不同的编程语言各有其特点和适用场景&#xff0c;选择合适的编程语言能够提高开发效率和软件质量。本文将对十种常见的编程语言进行对比分析&#xff0c;帮助读者了解它们的优缺点和适用场景。 Java 特点&…

Springboot微服务整合缓存的时候报循环依赖的错误 两种解决方案

错误再现 Error starting ApplicationContext. To display the conditions report re-run your application with debug enabled. 2024-06-17 16:52:41.008 ERROR 20544 --- [ main] o.s.b.d.LoggingFailureAnalysisReporter : *************************** APPLI…

git将代码提交到github

第一次代码提交 1.在github新建一个空白仓库 2、当前在文件下 3、git init 5、git add .(当前目录下所有代码全部提交) 6、git commit -n "init" 这次提交的备注信息 7、git branch -M main 8、git remote add origin (address) 9、git push -u origin main 第…

宝塔安装了redis但是远程无法连接

服务器&#xff1a;阿里云 宝塔版本&#xff1a;8.0.5 redis版本&#xff1a;7.2.4 操作步骤&#xff1a; 1.在阿里云上开放redis端口&#xff1a;6379 2.在宝塔上开发端口 3.修改redis配置文件&#xff1a; 修改一&#xff1a; 注释&#xff1a;bind 127.0.0.1&#xff0c;…

别再这么起号了!TikTok小白起号误区,你中招了吗?

看过不少Tiktok新手的起号失败案例&#xff0c;总结下来就是以下这几个问题&#xff0c;今天结合一些个人起号心得给大家分享怎么成功在TK起号&#xff0c;希望对大家有所帮助。 手机/网络环境 首先我们要确保手机环境和网络环境没有问题&#xff0c;如果被TK判断出是非海外用户…

一文看懂人工智能、机器学习、深度学习是什么、有什么区别!

引言&#xff1a;走进智能的世界 曾经&#xff0c;人工智能&#xff08;AI&#xff09;是科幻小说中的概念&#xff0c;与飞船、外星人并肩而立。 然而&#xff0c;随着时间的推移&#xff0c;AI不再仅仅是幻想的产物&#xff0c;它已经成为我们日常生活中不可或缺的一部分。 在…

成都爱尔胡建斌院长提醒一张眼底照,眼病早知道

眼底藏在眼睛后方&#xff0c;平时没注意无察觉&#xff0c;其实非常重要。它包含的部位多掌控着视觉问题&#xff0c;稍不注意就是视觉受损&#xff0c;视觉缺失&#xff0c;严重的甚至失明致盲。 眼球前面的角膜、晶体等&#xff0c;被称为眼前段&#xff0c;后面则被称之为…

PFA烧杯带把手带刻度1000ml3000mlPFA氟树脂温度范围-270~250℃

随着越来越多的痕量分析实验需要对ppb和ppt级的浓度进行测定。目前所使用的一般材料由于无特别处理&#xff0c;不可避免会与所储存的样品&#xff0c;试剂或标准液反应&#xff0c;导致痕量分析实验得到不正确的结果。但我厂的PFA产品刚好能弥补其不足。PFA金属元素空白值低&a…

STORM论文阅读笔记

这是篇NIPS2023的 world model 论文文章提出&#xff0c;WM的误差会在训练过程中积累从而影响policy的训练&#xff0c;向WM中加噪声可以改善这一点。其他的流程和IRIS差不多&#xff0c;差别在以下几点&#xff1a; image encoder&#xff0c;IRIS用的VQVAE, 本文用的是VAE&am…

QT属性系统,简单属性功能快速实现 QT属性的简单理解 属性学习如此简单 一文就能读懂QT属性 QT属性最简单的学习

4.4 属性系统 Qt 元对象系统最主要的功能是实现信号和槽机制&#xff0c;当然也有其他功能&#xff0c;就是支持属性系统。有些高级语言通过编译器的 __property 或者 [property] 等关键字实现属性系统&#xff0c;用于提供对成员变量的访问权限&#xff0c;Qt 则通过自己的元对…

从零开始学GeoServer源码(一)(搭建开发环境Win10+IDEA23.3.5+jdk11+geoserver2.24.x)

搭建开发环境 参考资料 0、基础环境准备0.1、idea0.2、jdk0.3、源码 1、导入工程2、配置启动环境2.1、打开新增配置面板2.2、配置工作目录2.2.1、从常用配置中选择2.2.2、直接粘贴 2.3最终效果 3、调整源码3.1、添加maven引用3.2、注释无效代码3.3、删除测试代码 4、修改运行端…