Mybatis返回Map对象的实现

 更新时间:2024年09月23日 10:26:37   作者:matrixlzp  
本文介绍了Mybatis和MybatisPlus在查询数据库时返回Map对象的多种实现方式,这些方法有助于优化DAO层代码,使其更加清晰和高效,下面就来具体介绍一下,感兴趣的可以了解一下

一、场景介绍

假设有如下一张学生表:

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 {

    @Autowired
    private StudentMapper mapper;

    @Override
    public 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 {

    @Autowired
    private StudentMapper mapper;

    @Override
    public 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 {

    @Autowired
    private StudentMapper mapper;

    @Override
    public 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 {

    @Override
    public 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 {

    @Override
    public 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 {

    @Override
    public 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 {

    @Override
    public 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对象的实现的文章就介绍到这了,更多相关Mybatis返回Map对象内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家! 

相关文章

  • 手动编译并运行Java项目实现过程解析

    手动编译并运行Java项目实现过程解析

    这篇文章主要介绍了手动编译并运行Java项目实现过程解析,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下
    2020-10-10
  • Java实现给图片添加图片水印,文字水印及马赛克的方法示例

    Java实现给图片添加图片水印,文字水印及马赛克的方法示例

    这篇文章主要介绍了Java实现给图片添加图片水印,文字水印及马赛克的方法,涉及java针对图片的读取、水印添加、马赛克设置等相关操作技巧,需要的朋友可以参考下
    2018-01-01
  • Java常见异常及处理方式总结

    Java常见异常及处理方式总结

    今天给大家带来的是Java的相关知识,文章围绕着Java异常展开,文中有非常详细的介绍及代码示例,需要的朋友可以参考下
    2021-06-06
  • 解决springboot 部署到 weblogic 中 jar 包冲突的问题

    解决springboot 部署到 weblogic 中 jar 包冲突的问题

    这篇文章主要介绍了springboot 部署到 weblogic 中 jar 包冲突,weblogic 也有是解决方案的,可以通过新增并配置 weblogic.xml 文件来定义哪些类需要优先从项目工程包的 jar 包中加载,本文给大家分享解决方法,需要的朋友可以参考下
    2022-08-08
  • Java中实现List分隔成子List详解

    Java中实现List分隔成子List详解

    大家好,本篇文章主要讲的是Java中实现List分隔成子List详解,感兴趣的同学赶快来看一看吧,对你有帮助的话记得收藏一下
    2022-01-01
  • Java 如何利用缓冲流读写文件

    Java 如何利用缓冲流读写文件

    这篇文章主要介绍了Java 如何利用缓冲流读写文件的操作,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2021-07-07
  • response.setContentType()参数以及作用详解

    response.setContentType()参数以及作用详解

    这篇文章主要介绍了response.setContentType()参数以及作用详解,本篇文章通过简要的案例,讲解了该项技术的了解与使用,以下就是详细内容,需要的朋友可以参考下
    2021-08-08
  • 解决RedisTemplate的key默认序列化器的问题

    解决RedisTemplate的key默认序列化器的问题

    这篇文章主要介绍了解决RedisTemplate的key默认序列化器的问题,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧
    2021-03-03
  • 详解Spring注解@Autowired的实现原理和使用方法

    详解Spring注解@Autowired的实现原理和使用方法

    在使用Spring开发的时候,配置的方式主要有两种,一种是xml的方式,另外一种是 java config的方式,在使用的过程中,我们使用最多的注解应该就是@Autowired注解了,所以本文就给大家讲讲@Autowired注解是如何使用和实现的,需要的朋友可以参考下
    2023-07-07
  • Springboot中MyBatisplus使用IPage和Page分页的实例代码

    Springboot中MyBatisplus使用IPage和Page分页的实例代码

    这篇文章主要介绍了Springboot中MyBatisplus使用IPage和Page分页,本文通过实例代码给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
    2020-12-12

最新评论