当前位置: 首页 > news >正文

Mybatis 返回 Map 对象

一、场景介绍

假设有如下一张学生表:

CREATE TABLE `student` (`id` int NOT NULL AUTO_INCREMENT COMMENT '主键',`name` varchar(100) NOT NULL COMMENT '姓名',`gender` varchar(10) NOT NULL COMMENT '性别',`grade` int NOT NULL COMMENT '年级',PRIMARY KEY (`id`)
) ENGINE=InnoDB COMMENT='学生信息表';

我们通过一组 ids,想获得 id 跟学生对象的映射 Map<Integer, Student>,可以这样做:

1、先通过 ids 获取对象列表

2、再通过 stream 流式运算得到 id-Student 映射

这样做虽然也没有问题,但是这样 service 层就会散落一堆这样流式运算的代码。不是很美观,应该在DAO层就提供这种能力。Mybatis 提供给我们查询 Map 的方式。

@Service
public class StudentServiceImpl implements StudentService {@Autowiredprivate StudentMapper mapper;@Overridepublic Map<Integer, Student> findMapByIds(List<Integer> ids) {List<Student> students = mapper.listByIds(ids);Map<Integer, Student> map = students.stream().collect(Collectors.toMap(Student::getId, Function.identity()));return map;}
}
---------------------------------------------------------------
@Test
public void test() {List<Integer> list = Arrays.asList(1,2,3);Map<Integer, Student> map = studentService.findMapByIds(list);System.out.println(map);
}输出:
{1=Student(id=1, name=小明, gender=male, grade=1), 2=Student(id=2, name=小红, gender=female, grade=2), 3=Student(id=3, name=小李, gender=male, grade=3)}

二、Mybatis @MapKey 方式

Mybatis 提供了 @MapKey 注解,注解的 value 用来指定 key 的取值字段。

可以看到,效果是一样的。

@Mapper
public interface StudentMapper {/*** 这种基础的查询,不应该先获取 List 流,然后再转换,* 这样会使整个项目散落一地这种代码* 应该在DAO层就提供这种能力*/@MapKey("id")Map<Integer, Student> findMapByIds(List<Integer> ids);
}
-------------------------------------------------------------
<?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.study.student.mapper.StudentMapper"><select id="findMapByIds" resultType="com.study.student.entity.Student">select *from student s<where>and s.id in<foreach collection="ids" item="id" open="(" separator="," close=")">#{id}</foreach></where></select></mapper>
-------------------------------------------------------------
@Service
public class StudentServiceImpl implements StudentService {@Autowiredprivate StudentMapper mapper;@Overridepublic Map<Integer, Student> findMapByIds(List<Integer> ids) {/*List<Student> students = mapper.listByIds(ids);Map<Integer, Student> map = students.stream().collect(Collectors.toMap(Student::getId, Function.identity()));return map;*/return mapper.findMapByIds(ids);}
}
-------------------------------------------------------------
@Test
public void test() {List<Integer> list = Arrays.asList(1,2,3);Map<Integer, Student> map = studentService.findMapByIds(list);System.out.println(map);
}
输出:
{1=Student(id=1, name=小明, gender=male, grade=1), 2=Student(id=2, name=小红, gender=female, grade=2), 3=Student(id=3, name=小李, gender=male, grade=3)}

 但如果 @MapKey 的 value 配置了记录重复的字段会怎么样?

就比如,@MapKey("grade"),grade = 1,2,3 的记录并非唯一。

@Mapper
public interface StudentMapper {List<Student> listByIds(List<Integer> ids);/*** @MapKey 的 value 是 grade 这种非唯一字段*/@MapKey("grade")Map<Integer, Student> findMapByIds(List<Integer> ids);
}

 这个时候会发现,返回的记录被覆盖了。

id in [1,6] 的 grade=1 的记录有 小明跟小智,

小明先查询出来,

map.put(1,  Student(id=1, name=小明, gender=male, grade=1))

小智后查询出来,

map.put(1,  Student(id=6, name=小智, gender=male, grade=1))

同一个key,小智覆盖了小明。

那如果我们希望返回 Map<grade:Integer, List<Student>> 怎么办呢?

@Test
public void test2() {List<Integer> list = Arrays.asList(1,2,3,4,5,6);Map<Integer, Student> map = studentService.findMapByIds(list);System.out.println(map);
}
输出:
{1=Student(id=6, name=小智, gender=male, grade=1), 2=Student(id=4, name=小林, gender=male, grade=2), 3=Student(id=5, name=小婷, gender=female, grade=3)}

三、Stream 返回 Map<Integer, List<Student>>

 遗憾的是,笔者找了 Mybatis 跟 MybatisPlus 也没找到此类方法,所以这一块,还是只能用流式计算来做。

@Mapper
public interface StudentMapper {List<Student> listByIds(List<Integer> ids);
}
-------------------------------------------------------------
<?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.study.student.mapper.StudentMapper"><select id="listByIds" resultType="cn.al.admin.entity.finance.Student">select *from student s<where>and s.id in<foreach collection="ids" item="id" open="(" separator="," close=")">#{id}</foreach></where></select></mapper>
-------------------------------------------------------------
@Service
public class StudentServiceImpl implements StudentService {@Autowiredprivate StudentMapper mapper;@Overridepublic Map<Integer, List<Student>> getMapByIds(List<Integer> ids) {List<Student> students = mapper.listByIds(ids);return students.stream().collect(Collectors.groupingBy(Student::getGrade));}
}
-------------------------------------------------------------
@Test
public void test3() {List<Integer> list = Arrays.asList(1,2,3,4,5,6);Map<Integer, List<Student>> map = studentService.getMapByIds(list);System.out.println(map);}
输出:
{1=[Student(id=1, name=小明, gender=male, grade=1), Student(id=6, name=小智, gender=male, grade=1)], 2=[Student(id=2, name=小红, gender=female, grade=2), Student(id=4, name=小林, gender=male, grade=2)], 3=[Student(id=3, name=小李, gender=male, grade=3), Student(id=5, name=小婷, gender=female, grade=3)]}

四、MybatisPlus 返回 List<Map<String, Object>>

如果希望查询返回 List<Map<String, Object>> Map 的 key 是数据库 column name

package com.study.student.mapper;import com.study.student.entity.Student;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import org.apache.ibatis.annotations.*;@Mapper
public interface StudentMapper extends BaseMapper<Student> {
}
------------------------------------------------------------
package com.study.student.service.impl;import com.study.student.entity.Student;
import com.study.student.mapper.StudentMapper;
import com.study.student.service.StudentService;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.springframework.stereotype.Service;import java.util.List;
import java.util.Map;@Service
public class StudentServiceImpl extends ServiceImpl<StudentMapper, Student> implements StudentService {@Overridepublic List<Map<String, Object>> getMapList(List<Integer> ids) {LambdaQueryWrapper<Student> wrapper = new LambdaQueryWrapper<>();wrapper.in(Student::getId, ids);return this.getBaseMapper().selectMaps(wrapper);}
}
------------------------------------------------------------
@Test
public void test4() {List<Integer> list = Arrays.asList(1,2,3,4,5,6);List<Map<String, Object>> map = studentService.getMapList(list);System.out.println(map);
}
输出:
[{gender=male, grade=1, name=小明, id=1, photo_url=url1}, {gender=female, grade=2, name=小红, id=2, photo_url=url2}, {gender=male, grade=3, name=小李, id=3, photo_url=url3}, {gender=male, grade=2, name=小林, id=4, photo_url=url4}, {gender=female, grade=3, name=小婷, id=5, photo_url=url5}, {gender=male, grade=1, name=小智, id=6, photo_url=url6}]

五、JSON 返回  List<Map<String, Object>>

如果希望查询返回 List<Map<String, Object>> Map 的 key 是对象 property。需要借助 JSON 工具类,比如 cn.hutool.core.bean.BeanUtil#beanToMap

package com.study.student.service.impl;import com.study.student.entity.Student;
import com.study.student.mapper.StudentMapper;
import com.study.student.service.StudentService;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.springframework.stereotype.Service;import cn.hutool.core.bean.BeanUtil;import java.util.List;
import java.util.Map;@Service
public class StudentServiceImpl extends ServiceImpl<StudentMapper, Student> implements StudentService {@Overridepublic List<Map<String, Object>> getMapList(List<Integer> ids) {List<Student> students = this.listByIds(ids);return students.stream().map(BeanUtil::beanToMap).collect(Collectors.toList());}
}
------------------------------------------------------------
@Test
public void test5() {List<Integer> list = Arrays.asList(1,2,3,4,5,6);List<Map<String, Object>> map = studentService.getMapList(list);System.out.println(map);
}
输出:
[{id=1, name=小明, gender=male, grade=1, photoUrl=url1}, {id=2, name=小红, gender=female, grade=2, photoUrl=url2}, {id=3, name=小李, gender=male, grade=3, photoUrl=url3}, {id=4, name=小林, gender=male, grade=2, photoUrl=url4}, {id=5, name=小婷, gender=female, grade=3, photoUrl=url5}, {id=6, name=小智, gender=male, grade=1, photoUrl=url6}]

六、MybatisPlus 返回 Map<String, Object>

Map 的 key 是数据库 column name

package com.study.student.service.impl;import com.study.student.entity.Student;
import com.study.student.mapper.StudentMapper;
import com.study.student.service.StudentService;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.springframework.stereotype.Service;import java.util.List;
import java.util.Map;@Service
public class StudentServiceImpl extends ServiceImpl<StudentMapper, Student> implements StudentService {@Overridepublic Map<String, Object> getMapById(Integer id) {LambdaQueryWrapper<Student> wrapper = new LambdaQueryWrapper<>();wrapper.eq(Student::getId, id);return this.getMap(wrapper);}
}
------------------------------------------------------------
@Test
public void test6() {Map<String, Object> map = studentService.getMapById(6);System.out.println(map);}
输出:
{gender=male, grade=1, name=小智, id=6, photo_url=url6}

 七、JSON 返回 Map<String, Object>

Map 的 key 是对象 property

package com.study.student.service.impl;import com.study.student.entity.Student;
import com.study.student.mapper.StudentMapper;
import com.study.student.service.StudentService;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.springframework.stereotype.Service;import cn.hutool.core.bean.BeanUtil;import java.util.List;
import java.util.Map;@Service
public class StudentServiceImpl extends ServiceImpl<StudentMapper, Student> implements StudentService {@Overridepublic Map<String, Object> getMapById(Integer id) {Student student = this.getById(id);return BeanUtil.beanToMap(student);}
}
------------------------------------------------------------
@Test
public void test7() {Map<String, Object> map = studentService.getMapById(6);System.out.println(map);
}
输出:
{id=6, name=小智, gender=male, grade=1, photoUrl=url6}

相关文章:

Mybatis 返回 Map 对象

一、场景介绍 假设有如下一张学生表&#xff1a; CREATE TABLE student (id int NOT NULL AUTO_INCREMENT COMMENT 主键,name varchar(100) NOT NULL COMMENT 姓名,gender varchar(10) NOT NULL COMMENT 性别,grade int NOT NULL COMMENT 年级,PRIMARY KEY (id) ) ENGINEInnoD…...

Vue3(三)路由基本使用、工作模式(history,hash)、query传参和param传参、props配置、编程式路由导航

文章目录 一、路由的基本使用二、路由器的工作模式三、RouterLink中to的两种写法四、嵌套路由五、路由传参1. query传参2. params传参 六、路由的propos配置七、编程式路由导航 一、路由的基本使用 安装&#xff1a;npm i vue-router 在src/pages文件下&#xff0c;创建三个路…...

TypeScript概念讲解

简单来说&#xff0c;TypeScript 是 JavaScript 的一个超集&#xff0c;支持 ECMAScript 6 标准&#xff1b; TypeScript 由微软开发的自由和开源的编程语言&#xff1b; TypeScript 设计目标是开发大型应用&#xff0c;它可以编译成纯 JavaScript&#xff0c;编译出来的 Jav…...

C++ | Leetcode C++题解之第437题路径总和III

题目&#xff1a; 题解&#xff1a; class Solution { public:unordered_map<long long, int> prefix;int dfs(TreeNode *root, long long curr, int targetSum) {if (!root) {return 0;}int ret 0;curr root->val;if (prefix.count(curr - targetSum)) {ret pref…...

回复《对话损友 2》

回复《对话损友 2》 承蒙贵人挂念&#xff0c;亦感激贵人给予这般交流的契机&#xff08;对话损友 2 -- 回复-CSDN博客&#xff09;。我自身也一直期望能留存些岁月的痕迹&#xff0c;然而却常困惑于不知哪些事物值得铭记&#xff0c;哪些又应被永远忘却。 随着时光流转&#x…...

MySQL - 运维篇

一、日志 1. 错误日志 2. 二进制日志 3. 查询日志 记录了所有的增删改查语句以及DDL语句 4. 慢查询日志 二、主从复制 1. 概述 2. 原理 3. 搭建 三、分库分表 1. 介绍 2. Mycat概述 3. Mycat入门 4. Mycat配置 5. Mycat分片 6. Mycat管理及监控 四、读写分离 1. 介绍 2. 一…...

WebGIS开发及市面上各种二三维GIS开发框架对比分析

GIS前端开发是现代WebGIS应用开发中非常重要的一环&#xff0c;通过前端开发框架&#xff0c;可以实现地图展示、交互、分析等功能。本文将介绍当前市面上常用的GIS前端开发框架&#xff0c;并进行对比分析。 Leaflet Leaflet是一款轻量级的开源地图库&#xff0c;它提供了丰…...

[论文精读]TorWard: Discovery, Blocking, and Traceback of Malicious Traffic Over Tor

期刊名称&#xff1a;IEEE Transactions on Information Forensics and Security 发布链接&#xff1a;TorWard: Discovery, Blocking, and Traceback of Malicious Traffic Over Tor | IEEE Journals & Magazine | IEEE Xplore 中文译名&#xff1a;TorWard&#xff1a;…...

pytest - 多线程提速

import timedef test1_test1():time.sleep(1)assert 1 1, "11"def test1_test2():time.sleep(1)assert 1 1, "11" 上面2个函数&#xff0c;执行情况&#xff1a; 正常执行时&#xff0c;花费 2.08s2个进程执行时&#xff0c;花费 1.18s2个线程执行时&a…...

python中logging的用法

logging.error 是 Python logging 模块中的一个方法&#xff0c;专门用于记录错误级别&#xff08;ERROR&#xff09;的日志信息。logging 模块是 Python 提供的标准日志工具&#xff0c;用于生成各种级别的日志消息&#xff0c;并支持日志的格式化和存储。 logging.error 的基…...

【YOLO目标检测车牌数据集】共10000张、已标注txt格式、有训练好的yolov5的模型

目录 说明图片示例 说明 数据集格式&#xff1a;YOLO格式 图片数量&#xff1a;10000&#xff08;2000张绿牌、8000张蓝牌&#xff09; 标注数量(txt文件个数)&#xff1a;10000 标注类别数&#xff1a;1 标注类别名称&#xff1a;licence 数据集下载&#xff1a;车牌数据…...

gdb xterm 调试 openmpi 程序

1&#xff0c;编写编译一个openmpi程序 迭代计算 PI 的源程序&#xff1a; pi_reduce.c #include <stdio.h>#include <math.h> #include <mpi.h>double f(double); double f(double x) {return (4.0/(1.0x*x)); }int main(int argc, char* argv[]) {int d…...

【STM32】江科大STM32笔记汇总(已完结)

STM32江科大笔记汇总 STM32学习笔记课程简介(01)STM32简介(02)软件安装(03)新建工程(04)GPIO输出(05)LED闪烁& LED流水灯& 蜂鸣器(06)GPIO输入(07)按键控制LED 光敏传感器控制蜂鸣器(08)OLED调试工具(09)OLED显示屏(10)EXTI外部中断(11)对射式红外传感器计次 旋转编码器…...

Java基础扫盲(二)

想看Java基础扫盲&#xff08;一&#xff09;的可以观看我的上篇文章Java基础扫盲 目录 String为什么设计为不可变的 String有长度限制吗 为什么JDK9将String的char[]改为byte[] 泛型中K,T,V,E,Object,?等都代表什么含义 怎么修改一个类中使用了private修饰的String类型…...

兼容React的刮刮乐完整代码实现

需要兼容React的刮刮乐完整代码实现 在现代Web开发中&#xff0c;React作为一种流行的前端框架&#xff0c;为开发者提供了构建动态界面的强大工具。刮刮乐效果作为一种趣味性的用户交互&#xff0c;能够显著提升用户体验和参与度。本文将详细介绍如何在React项目中实现一个兼…...

PHP程序如何实现限制一台电脑登录?

PHP程序如何实现限制一台电脑登录&#xff1f; 可以使用以下几种方法&#xff1a; 1. IP地址限制&#xff1a;在PHP中&#xff0c;可以通过获取客户端的IP地址&#xff0c;然后与允许登录的IP地址列表进行比对。如果客户端的IP地址不在列表中&#xff0c;就禁止登录。 “php $…...

nodejs fs 模块的简介与相关案例

fs 文件系统模块 什么是 fs 文件系统模块&#xff1f; fs 模块是 Node.js 官方提供的、用来操作文件的模块。它提供了一系列的方法和属性&#xff0c;用来满足用户对文件的操作要求。* 例如&#xff1a; fs.readFile() 方法用来读取文件内容。fs.writeFile() 方法用来写入文…...

计算机毕业设计 基于Flask+Vue的博客系统 Python毕业设计 前后端分离 附源码 讲解 文档

&#x1f34a;作者&#xff1a;计算机编程-吉哥 &#x1f34a;简介&#xff1a;专业从事JavaWeb程序开发&#xff0c;微信小程序开发&#xff0c;定制化项目、 源码、代码讲解、文档撰写、ppt制作。做自己喜欢的事&#xff0c;生活就是快乐的。 &#x1f34a;心愿&#xff1a;点…...

基于SSH的酒店管理系统的设计与实现 (含源码+sql+视频导入教程)

&#x1f449;文末查看项目功能视频演示获取源码sql脚本视频导入教程视频 1 、功能描述 基于SSH的酒店管理系统拥有两种角色 管理员&#xff1a;房间管理、房型管理、客户管理、预定管理、入住管理&#xff08;到店入住、预定入住、正在入住&#xff09;、账单管理、会员管理…...

消息队列10:为RabbitMq添加连接池

环境&#xff1a; win11rabbitmq-3.8.17.net 6.0RabbitMQ.Client 6.8.1vs2022 安装RabbitMq环境参照&#xff1a; window下安装rabbitmqlinux下安装rabbitmq 问题&#xff1a;rabbitmq的c#客户端没有自带连接池&#xff0c;所以需要手动实现。 简易实现如下&#xff1a; usi…...

web vue 项目 Docker化部署

Web 项目 Docker 化部署详细教程 目录 Web 项目 Docker 化部署概述Dockerfile 详解 构建阶段生产阶段 构建和运行 Docker 镜像 1. Web 项目 Docker 化部署概述 Docker 化部署的主要步骤分为以下几个阶段&#xff1a; 构建阶段&#xff08;Build Stage&#xff09;&#xff1a…...

前端导出带有合并单元格的列表

// 导出async function exportExcel(fileName "共识调整.xlsx") {// 所有数据const exportData await getAllMainData();// 表头内容let fitstTitleList [];const secondTitleList [];allColumns.value.forEach(column > {if (!column.children) {fitstTitleL…...

大语言模型如何处理长文本?常用文本分割技术详解

为什么需要文本分割? 引言:为什么需要文本分割?一、基础文本分割方法1. 按段落分割(Paragraph Splitting)2. 按句子分割(Sentence Splitting)二、高级文本分割策略3. 重叠分割(Sliding Window)4. 递归分割(Recursive Splitting)三、生产级工具推荐5. 使用LangChain的…...

数据库分批入库

今天在工作中&#xff0c;遇到一个问题&#xff0c;就是分批查询的时候&#xff0c;由于批次过大导致出现了一些问题&#xff0c;一下是问题描述和解决方案&#xff1a; 示例&#xff1a; // 假设已有数据列表 dataList 和 PreparedStatement pstmt int batchSize 1000; // …...

UR 协作机器人「三剑客」:精密轻量担当(UR7e)、全能协作主力(UR12e)、重型任务专家(UR15)

UR协作机器人正以其卓越性能在现代制造业自动化中扮演重要角色。UR7e、UR12e和UR15通过创新技术和精准设计满足了不同行业的多样化需求。其中&#xff0c;UR15以其速度、精度及人工智能准备能力成为自动化领域的重要突破。UR7e和UR12e则在负载规格和市场定位上不断优化&#xf…...

VM虚拟机网络配置(ubuntu24桥接模式):配置静态IP

编辑-虚拟网络编辑器-更改设置 选择桥接模式&#xff0c;然后找到相应的网卡&#xff08;可以查看自己本机的网络连接&#xff09; windows连接的网络点击查看属性 编辑虚拟机设置更改网络配置&#xff0c;选择刚才配置的桥接模式 静态ip设置&#xff1a; 我用的ubuntu24桌…...

LINUX 69 FTP 客服管理系统 man 5 /etc/vsftpd/vsftpd.conf

FTP 客服管理系统 实现kefu123登录&#xff0c;不允许匿名访问&#xff0c;kefu只能访问/data/kefu目录&#xff0c;不能查看其他目录 创建账号密码 useradd kefu echo 123|passwd -stdin kefu [rootcode caozx26420]# echo 123|passwd --stdin kefu 更改用户 kefu 的密码…...

打手机检测算法AI智能分析网关V4守护公共/工业/医疗等多场景安全应用

一、方案背景​ 在现代生产与生活场景中&#xff0c;如工厂高危作业区、医院手术室、公共场景等&#xff0c;人员违规打手机的行为潜藏着巨大风险。传统依靠人工巡查的监管方式&#xff0c;存在效率低、覆盖面不足、判断主观性强等问题&#xff0c;难以满足对人员打手机行为精…...

Spring AI Chat Memory 实战指南:Local 与 JDBC 存储集成

一个面向 Java 开发者的 Sring-Ai 示例工程项目&#xff0c;该项目是一个 Spring AI 快速入门的样例工程项目&#xff0c;旨在通过一些小的案例展示 Spring AI 框架的核心功能和使用方法。 项目采用模块化设计&#xff0c;每个模块都专注于特定的功能领域&#xff0c;便于学习和…...

水泥厂自动化升级利器:Devicenet转Modbus rtu协议转换网关

在水泥厂的生产流程中&#xff0c;工业自动化网关起着至关重要的作用&#xff0c;尤其是JH-DVN-RTU疆鸿智能Devicenet转Modbus rtu协议转换网关&#xff0c;为水泥厂实现高效生产与精准控制提供了有力支持。 水泥厂设备众多&#xff0c;其中不少设备采用Devicenet协议。Devicen…...