当前位置: 首页 > 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}

http://www.lryc.cn/news/449430.html

相关文章:

  • Vue3(三)路由基本使用、工作模式(history,hash)、query传参和param传参、props配置、编程式路由导航
  • TypeScript概念讲解
  • C++ | Leetcode C++题解之第437题路径总和III
  • 回复《对话损友 2》
  • MySQL - 运维篇
  • WebGIS开发及市面上各种二三维GIS开发框架对比分析
  • [论文精读]TorWard: Discovery, Blocking, and Traceback of Malicious Traffic Over Tor
  • pytest - 多线程提速
  • python中logging的用法
  • 【YOLO目标检测车牌数据集】共10000张、已标注txt格式、有训练好的yolov5的模型
  • gdb xterm 调试 openmpi 程序
  • 【STM32】江科大STM32笔记汇总(已完结)
  • Java基础扫盲(二)
  • 兼容React的刮刮乐完整代码实现
  • PHP程序如何实现限制一台电脑登录?
  • nodejs fs 模块的简介与相关案例
  • 计算机毕业设计 基于Flask+Vue的博客系统 Python毕业设计 前后端分离 附源码 讲解 文档
  • 基于SSH的酒店管理系统的设计与实现 (含源码+sql+视频导入教程)
  • 消息队列10:为RabbitMq添加连接池
  • 在使用 Docker 时,用户可能会遇到各种常见的错误和问题
  • MinIO使用客户端进行桶和对象的管理
  • 数据库管理-第244期 一次无法switchover的故障处理(20240928)
  • 太绝了死磕这本大模型神书!
  • Kevin‘s notes about Qt---Episode 6 不同类中创建同一对象
  • YOLOv9改进策略【Conv和Transformer】| AssemFormer 结合卷积与 Transformer 优势,弥补传统方法不足
  • Git 的安装和配置
  • InternVL 微调实践
  • 自然语言处理在人工智能领域的发展历程,以及NLP重点模型介绍
  • Replit Agent:AI驱动的全自动化软件开发革命
  • SAP调用发起泛微OA流程