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

项目场景:

  在使用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{@Autowiredprivate 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")   //指定keyMap<Integer, Map<String, Object>> tooMany();

Service测试:  

@Service
public class TestService{@Autowiredprivate 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<>();@Overridepublic 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{@Autowiredprivate 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{@Autowiredprivate 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.mzph.cn/news/854827.shtml

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

相关文章

编程大赛的题怎么做:策略、技巧与实战经验

编程大赛的题怎么做&#xff1a;策略、技巧与实战经验 编程大赛&#xff0c;作为一场集智慧、技巧与实战经验于一体的较量&#xff0c;吸引了无数编程爱好者的参与。然而&#xff0c;面对复杂多变的题目和激烈的竞争环境&#xff0c;如何有效地解题并脱颖而出&#xff0c;成为…

【Unity】向量应用:已知入射方向和法向量求反射方向(跳弹系统)

文章目录 已知入射方向和法向量求反射方向已知条件解题思路代码范例 已知入射方向和法向量求反射方向 已知条件 已知入射向量v1和法向量n&#xff08;OB&#xff09;&#xff0c;求反射向量v2&#xff0c;上述向量均为单位向量。 解题思路 设 AO为 v1 &#xff1b;OB为 n …

ABAP随笔记

1:/nsxi_monitor查看接口日志 2:内表数据拼接 2.1、给内表加一个空行并修改他的值 APPEND INITIAL LINE TO GT_ALV ASSIGNING FIELD-SYMBOL(<FS>) .2.2、将内表数据拼接在一行 CONCATENATE LINES

外贸独立站做了没效果怎么办

如果外贸独立站做了但没有达到预期的效果&#xff0c;可以考虑以下几个方面来进行优化和改进&#xff1a; 1. 优化网站内容&#xff1a;确保网站内容高质量、专业且符合目标市场的需求。更新内容以保持网站的活跃度和相关性。 2. 搜索引擎优化(SEO)&#xff1a;对网站进行SEO…

实验13 BGP路径选择

实验13 BGP路径选择 一、 原理描述二、 实验目的三、 实验内容四、 实验配置五、 实验步骤 一、 原理描述 与域内路由不同&#xff0c;域间路由更加注重策略&#xff0c;而不是技术。在域内进行选路&#xff0c;可以使用路由算法计算出到达目的子网的最短路径&#xff1b;而在…

如何完美解决 Oracle Database 19c 安装程序 - 第7步(共8步)卡住,半小时都不动

&#x1f680; 如何完美解决 Oracle Database 19c 安装程序 - 第7步&#xff08;共8步&#xff09;卡住&#xff0c;半小时都不动 摘要 在安装 Oracle Database 19c 时&#xff0c;很多用户会在第7步&#xff08;共8步&#xff09;遇到卡住的问题&#xff0c;尤其是安装程序长…

行业模板|DataEase应用平台对接大屏模板推荐

DataEase开源数据可视化分析工具于2022年6月发布模板市场&#xff08;https://templates-de.fit2cloud.com&#xff09;&#xff0c;并于2024年1月新增适用于DataEase v2版本的模板分类。模板市场旨在为DataEase用户提供专业、美观、拿来即用的大屏模板&#xff0c;方便用户根据…

Spring框架的最新进展:2023年Spring Boot和Spring Cloud功能更新

引用 Spring框架的最新动态&#xff1a;2023年Spring Boot与Spring Cloud功能升级 Spring框架作为Java开发领域的重要技术之一&#xff0c;一直致力于简化开发流程和提高开发效率。2023年&#xff0c;Spring Boot和Spring Cloud两大核心组件再次迎来功能升级&#xff0c;为开…

【杂记-浅谈虚拟类型终端VTY用户界面】

一、VTY概述 VTY是Virtual Teletype Terminal的缩写&#xff0c;指的是路由器或交换机的远程登录的虚拟端口。这些虚拟端口允许用户通过Telnet或SSH协议连接到网络设备进行管理和维护操作。 user-interface vty 是华为设备中的一个重要配置命令&#xff0c;主要用于配置虚拟类…

哪个充电宝牌子好用又实惠?盘点四大平价充电宝分享

在当今快节奏的生活中&#xff0c;充电宝已成为我们日常生活中不可或缺的一部分。然而&#xff0c;面对市场上琳琅满目的充电宝品牌和型号&#xff0c;许多消费者误以为选择容量越大、价格越高的充电宝就是最好的选择。实际上&#xff0c;买充电宝并不是一味追求高容量和高价格…

深入解析知识付费平台的核心功能模块:满足个性化学习需求的数字化教育新星

在数字化学习的大潮中&#xff0c;知识付费平台已成为教育行业的一颗新星&#xff0c;它以满足用户需求为核心&#xff0c;提供便捷高效的学习渠道。该平台汇聚了各类专业知识&#xff0c;覆盖职业技能、生活兴趣和人文社科等多个领域&#xff0c;满足不同用户的学习需求。同时…

laravel Blade 指令的趣味性

首先,我们通过几个要点来解释 Blade 引擎的工作原理。 您选择一个 Blade 模板进行渲染。引擎使用一系列正则表达式来解析和编译模板。该引擎生成一个普通的 PHP 文件并将其写入磁盘(以便将其缓存以供将来渲染)。包含 PHP 文件并使用输出缓冲区来捕获生成的 HTML。该过程中最…

【scrapy】爬虫,从429状态码说起

许久未爬&#xff0c;发现爬不动了&#xff0c;哈哈哈&#xff0c;记录下这次失败的爬取经历 问题描述 针对这样的一个网站&#xff1a; https://www.farfetch.cn/cn/shopping/women/dresses-1/items.aspx?page1&view96&sort3 需求&#xff1a; 1.需要爬取列表页…

TOP10!YashanDB斩获广东省优秀信创产品与解决方案双料荣誉

近日&#xff0c;2024广东软件风云榜结果出炉&#xff0c;表彰为广东软件产业和数字经济、新型工业化发展作出突出贡献的企业、企业家、优秀产品等。深算院崖山数据库系统 YashanDB荣获广东省“2024年优秀信息技术应用创新产品TOP10”和“2024年优秀信息技术应用创新行业应用解…

java 对象实际占用内存大小预估工具类ObjectSizeUtil

java 对象实际占用内存大小预估工具类 返回对象占用预估字节数 返回字节数对应格式化后的字符串&#xff08;xx Kb&#xff09; 使用效果 依赖了lombock和hutool&#xff0c;项目不用这个可以去掉日志&#xff0c;稍微改写一下。 import cn.hutool.core.util.ClassUtil; i…

JavaScript中的Function

** 一、Function ** 什么是&#xff1a; 用途&#xff1a;保存一段可重用的代码段的程序结构&#xff0c;再起一个名字。本质&#xff1a;内存中保存一段代码段的存储空间------对象为什么&#xff1a;只要一段代码&#xff0c;可能被反复使用时&#xff0c;都要定义在一个函…

Shell 学习笔记 - 变量的删除、替换和替代 + 变量中的特殊符号

1.9 Shell 变量的删除、替换和替代 Linux 提供一些可以直接对变量进行操作的符号。通过这些符号&#xff0c;变量中的部分内容可以被删除、替换和替代。在 Shell 中&#xff0c;变量的删除、替换和替代也是非常重要的。通过简单操作修改变量&#xff0c;可以减少代码的行数并提…

docker怎么拉取全部镜像,打包所有镜像

因为docker&#xff0c;所以我把电脑上之前的镜像全部打包出来了 你们也可以打包&#xff0c;我提供一个脚本&#xff0c;你运行即可 export_docker.sh #!/bin/bash# 导出目录 EXPORT_DIR"docker_images_backup" mkdir -p "$EXPORT_DIR"# 获取所有镜像 …

编程第一课名字怎么写:创意、吸引力与实用性的完美结合

编程第一课名字怎么写&#xff1a;创意、吸引力与实用性的完美结合 在编程教育的世界里&#xff0c;为第一课起一个引人入胜的名字至关重要。这个名字不仅要能够吸引学生的注意&#xff0c;还要能够准确地传达课程的核心内容和价值。那么&#xff0c;如何为编程第一课起一个既…

PythonPoc基础编写(3)---批量刷cnvd

文章目录 前言一、发现过程二、使用步骤1.引入库2.读入数据结果 总结 前言 想刷cnvd&#xff1f;最重要的是登录进行测试功能点 一、发现过程 找到一个网站 发现登录失败返回200 登录成功则是重定向 302 那就写一个脚本吧 二、使用步骤 1.引入库 import requests 2.读入…