MyBatis自定义映射resultMap,处理一对多,多对一

news2024/11/27 6:17:22

1、自定义映射resultMap

复习:查询的标签select必须设置属性resultType或resultMap,用于设置实体类和数据库表的映射 关系

resultType:自动映射,用于属性名和表中字段名一致的情况 (或设置了下划线映射为驼峰)。

resultMap:自定义映射,用于一对多或多对一或字段名和属性名不一致的情况

1.1、resultMap处理字段和属性的映射关系

若字段名和实体类中的属性名不一致,则可以通过resultMap设置自定义映射。

(补充:当字段名和属性名一样时,字段和属性是一 一对应的,jdbc会通过反射实现这种对应,所以,能查到完整的对象。当不一样时,又没有自己处理,那字段和属性就对应不上,查出来的对象属性全是null)

<!--
	select标签里的resultMap属性设置使用哪个映射规则
    resultMap标签:设置自定义映射(自定义字段和属性的映射规则)
            	属性: id:表示自定义映射的唯一标识,即给你这个具体的映射规则resultMap起一个唯一名字
                	  type:查询的数据要映射的实体类的类型
    子标签:
        id标签:设置主键的映射关系
        result标签:设置普通字段的映射关系。即你想要你的结果是怎么映射的,怎么一一对应填值的
        association标签:设置多对一的映射关系。比如Employee类中有一个Department属性
        collection标签:设置一对多的映射关系。比如Department类中有一个。List<Employee>属性
        属性:
        property:设置映射关系中实体类中的属性名,必须是java中实体类的属性名
        column:设置映射关系中的字段名.必须是sql查询出的某个字段(出现在sql查询语句的字段)
因为是自定义,所以,java中的属性名不是驼峰的也可,mysql里的属性不是_也可。
		property和column的先后位置任意
-->
<resultMap id="userResultMap" type="User">
    <id property="userId" column="userid"></id>
    <result property="userName" column="user_name"></result>
    <result property="password" column="password"></result>
    <result property="age" column="age"></result>
    <result property="sex" column="sex"></result>
</resultMap>
<!--List<User> testMohu(@Param("mohu") String mohu);使用刚才定义的映射规则-->
<select id="testMohu" resultMap="userResultMap">
    <!--select * from t_user where username like '%${mohu}%'-->
    select id,user_name,password,age,sex from t_user where user_name like concat('%',#{mohu},'%')
</select>

若字段名和实体类中的属性名不一致,但是字段名符合数据库的规则,实体类中的属性 名符合Java的规则, 此时也可通过以下3种方式处理字段名和实体类中的属性的映射关系

a>可以通过为字段起别名的方式,保证和实体类中的属性名保持一致

b>可以在MyBatis的核心配置文件中设置一个全局配置信息mapUnderscoreToCamelCase,可 以在查询表中数据时,自动将_类型的字段名转换为驼峰 (推荐)

例如:字段名user_name,设置了mapUnderscoreToCamelCase,此时字段名就会转换为 userName

c> 使用resultMap

1.2、多对一映射处理(对象属性)

场景模拟:

查询员工信息以及员工所对应的【部门信息】

员工表和部门表的关系是多对一

1.2.1、级联方式处理映射关系

多对一映射:多位员工Emp对应一个部门Dept

public class Emp {
    private Integer empId;
    private String empName;
    private Integer age;
    private String gender;
    //查询员工对应的部门信息时,必须要在Emp类中写一个Dept属性。且提供 get、set,构造器不用加上dept
    // 表与表有关系,在数据库中,员工表里有部门id字段。
    //表与表之间的关系体现在java中,就是在类中加入对象属性。因为员工和部门是多对一的关系,所以,在员工类中
    // 加一个Dept类型的属性。  
    //补充:若是一对多,那要在少的一方加一个集合,比如,在Dept里里加一个List<Emp>类型的属性.
    ///根据需求判断 只在一方加,还是两方都加。
    private Dept dept;//这就是所谓的  对象属性
    
   public Emp() {
    }

    public Emp(Integer empId, String empName, Integer age, String gender) {
        this.empId = empId;
        this.empName = empName;
        this.age = age;
        this.gender = gender;
    }
    。。。。。。
	//提供所有属性的get、set方法,重写toString
}
public class Dept {
    private Integer deptId;
    private String depName;
    public Dept() {
    }

    public Dept(Integer deptId, String depName) {
        this.deptId = deptId;
        this.depName = depName;
    }
    。。。。。。。。。。。。。。。。。。。。。。。
    //提供所有属性的get、set方法,重写toString
}

Mapper接口:

public interface EmpMapper {
    /**
     * 查询指定员工的信息以及他所在部门的信息
     * @param empId
     * @return
     */
    Emp getEmpAndDeptByEid(@Param("empId") int empId);
}

想明白字段该和哪个属性进行映射

因为dept是Emp类里的对象属性,所以,字段dept_name 对应 dept.depName

    <resultMap id="empDeptMap" type="Emp">
        <id column="emp_id" property="empId"></id>
        <result column="emp_name" property="empName"></result>
        <result column="age" property="age"></result>
        <result column="gender" property="gender"></result>
        
        <!--这里仍然用result标签。需要部门表里的哪几些字段,这就写几个,但要保证java类中有属性,且提供了get、set方法。dept是Emp类中的属性,depName是dept对象的属性,实际调用getDeptName方法-->
        <result column="dept_name" property="dept.depName"></result>
    </resultMap>
    <!--Emp getEmpAndDeptByEid(@Param("empId") int empId);-->
    <select id="getEmpAndDeptByEid" resultMap="empDeptMap">
        SELECT t_emp.*, t_dept.dept_name
        FROM t_emp NATURAL JOIN t_dept
        WHERE t_emp.emp_id=#{empId}
    </select>

根据自己具体业务需求写SQL语句,有时候可能写成外连接。

1.2.2、使用association处理映射关系(推荐)

同上。需要先在java类Emp中添加一个属性private Dept dept ;并提供get、set方法,构造器不用加上dept。重写toString。

association标签:处理多对一的映射关系(处理实体类类型的属性)。比如Employee类中有一个Department属性

用上这个标签更好理解,阅读也方便。我个人比较喜欢这种方式。

将映射文件写成下面这样:

    <resultMap id="empDeptMap" type="Emp">
        <id column="emp_id" property="empId"></id>
        <result column="emp_name" property="empName"></result>
        <result column="age" property="age"></result>
        <result column="gender" property="gender"></result>
        <!--<result column="dept_name" property="dept.deptName"></result>-->
        <!--<result column="dept_id" property="dept.deptId"></result>-->
        <!--只有这发生了变化。-->
        <association property="dept" javaType="Dept">
            <!--也是需要哪些部门表中的字段,就写哪些。因为我的部门表里总共2个字段,而且查的是t_dept.*,所以,我这写了2个。 -->
            <id column="dept_id" property="deptId"></id>
            <result column="dept_name" property="deptName"></result>
      
        </association>
    </resultMap>

    <!--Emp getEmpAndDeptByEid(@Param("empId") int empId);-->
    <select id="getEmpAndDeptByEid" resultMap="empDeptMap">
        SELECT t_emp.*, t_dept.*
        FROM t_emp NATURAL JOIN t_dept
        WHERE t_emp.emp_id=#{empId}
    </select>
  @Test
    public void testEmpDept(){
        SqlSession sqlSession = sqlSessionUtils.getSqlSession();
        EmpMapper mapper = sqlSession.getMapper(EmpMapper.class);
        Emp empAndDeptByEid = mapper.getEmpAndDeptByEid(1);
        System.out.println(empAndDeptByEid);
        //Emp{empId=1, empName='赵四', age=20, gender='男', dept=Dept{deptId=1, depName='a部门'}}

    }
1.2.3、分步查询

文字记录不太清楚

去看尚硅谷杨博超老师的SSM视频。或其他学习资源

1.3、一对多映射处理( 集合属性)

多对一反过来就是一对多,一个部门对应多个员工。需要在部门类中加一个List<Emp> emps属性,提供get、set方法,toString。 构造器中不用加List<Emp> emps处理一对多的映射关系:

  • 方式一:collection

  • 方式二:分步查询

public class Dept {
    private Integer deptId;
    private String deptName;
	//一对多,一个部门里有多个员工
    private List<Emp> emps;
    ..........
}

需求:根据部门id查询部门以及该部门中所有员工的信息

1.3.1、collection

根据具体业务需要写sql语句,看是否需要使用左外连接或右外连接. 例如下面的左外连接,因为有的人没有部门,但是又想查所有人。

SELECT *
FROM t_dept
LEFT JOIN t_emp ON t_dept.dept_id = t_emp.dept_id
WHERE t_dept.dept_id=#{deptId}

* 表示查询2表的所有字段

我的例子用的是自然连接:

SELECT *  # 两个表的所有字段
FROM t_dept
NATURAL JOIN t_emp WHERE t_dept.dept_id=#{deptId}
DeptMapper接口里:
/**
* 根据部门id查新部门以及该部门中的员工信息
* @param did
* @return
*/
  Dept getDeptAndEmpByDeptId(@Param("deptId") int deptId);
   DeptMapper.xml 里:

<resultMap id="deptAndEmpResultMap" type="Dept">
        <id column="dept_id" property="deptId"></id>
        <result column="dept_name" property="deptName"></result>
    <!--collection标签:处理一对多的关系映射(处理属性为集合类型的)。一个Dept对象里有多个Emp对象-->
        <!--ofType属性:设置集合里面存储的数据类型是啥。存储的是Emp类型-->
        <!--因为collection标签已经说明是了处理集合的,所以不能用javaType
collection是集合的意思,List<Emp>正好是一个集合,所以用来处理一对多-->
        <collection property="emps" ofType="Emp">
            <id column="emp_id" property="empId"></id>
            <result column="emp_name" property="empName"></result>
            <result column="age" property="age"></result>
            <result column="gender" property="gender"></result>
        </collection>
    </resultMap>
    <!--Dept getDeptAndEmpByDeptId(@Param("deptId") int deptId);-->
    <select id="getDeptAndEmpByDeptId" resultMap="deptAndEmpResultMap">
        SELECT t_dept.*,t_emp.*
        FROM t_dept
                 NATURAL JOIN t_emp WHERE t_dept.dept_id=#{deptId}
    </select>
    @Test
    public void testGetDeptAndEmpByDeptId(){
        SqlSession sqlSession = sqlSessionUtils.getSqlSession();
        DeptMapper mapper = sqlSession.getMapper(DeptMapper.class);
        Dept deptAndEmpByDeptId = mapper.getDeptAndEmpByDeptId(1);
        System.out.println(deptAndEmpByDeptId);

    }

DEBUG 09-16 19:51:25,389 ==>  Preparing: SELECT t_dept.*,t_emp.* FROM t_dept NATURAL JOIN t_emp WHERE t_dept.dept_id=? (BaseJdbcLogger.java:137) 
DEBUG 09-16 19:51:25,421 ==> Parameters: 1(Integer) (BaseJdbcLogger.java:137) 
DEBUG 09-16 19:51:25,455 <==      Total: 2 (BaseJdbcLogger.java:137) 
    
Dept{deptId=1, deptName='a部门',
     emps=[
           Emp{empId=1, empName='aaaa', age=20, gender='男', dept=null},
           Emp{empId=2, empName='bbbb', age=23, gender='男', dept=null}
          ]
    }

个人理解:

association 是“关系,关联”的意思,专门用来 负责属性为实体类对象(非List集合)时的映射规则,

collection 是“集合”的意思,专门用来负责属性为List<xxx> 时的映射规则。

所以,association负责“多对一”,collection负责”一对多“

1.3.2、分步查询

去看尚硅谷杨博超老师的SSM视频。或其他学习资源

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

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

相关文章

qemu基础篇——VSCode 配置 GDB 调试

文章目录 VSCode 配置 GDB 调试安装 VSCode 插件调试文件创建调试配置配置脚本qemu 启动脚 启动调试报错情况一报错情况二报错情况三 调试界面运行 GDB 命令查看反汇编断点查看内核寄存器查看变量参考链接 VSCode 配置 GDB 调试 上一节中直接使用 GDB 命令行调试&#xff0c;本…

基于海洋捕食者优化的BP神经网络(分类应用) - 附代码

基于海洋捕食者优化的BP神经网络&#xff08;分类应用&#xff09; - 附代码 文章目录 基于海洋捕食者优化的BP神经网络&#xff08;分类应用&#xff09; - 附代码1.鸢尾花iris数据介绍2.数据集整理3.海洋捕食者优化BP神经网络3.1 BP神经网络参数设置3.2 海洋捕食者算法应用 4…

JVM字节码指令详解

文章目录 前言一、JVM字节码指令概述1. 什么是JVM字节码指令&#xff1a;2. 字节码指令的作用&#xff1a;3. 字节码指令的分类&#xff1a; 二、字节码指令的种类1. 加载和存储指令2. 算术指令3. 类型转换指令4. 对象和数组操作指令5. 操作数栈管理指令6. 控制转移指令7. 方法…

在emacs中,设置latex的主文档

文档&#xff1a; chapter1.tex chapter2.tex main.tex 在chapter1.tex中&#xff0c;先按下 ctrlc ctrln&#xff0c;再按下ctrlc ctrla&#xff0c;在下方的提示框中输入主文档。

链路层3:VLAN的配置与分析

VLAN的帧格式 VLAN数据帧的传输 在以太网中&#xff0c;加了标签tag的VLAN数据帧我们叫做V-MAC帧&#xff0c;普通的数据帧我们叫做MAC帧。对于主机来说&#xff0c;它只认识普通的MAC帧&#xff1b;对于主机&#xff0c;V-MAC帧和MAC帧它都认。所以&#xff0c;实际上的V-MAC…

docker中使用GPU+rocksdb

配置环境 delldell-Precision-3630-Tower  ~  lsb_release -a No LSB modules are available. Distributor ID: Ubuntu Description: Ubuntu 20.04.6 LTS Release: 20.04 Codename: focaldelldell-Precision-3630-Tower  ~  nvcc --version nvcc: NVIDIA (R) Cuda comp…

如果C盘满了怎么办

相信这个问题是困扰了很多人的。 1、清理 1.1清理缓存 这种适合一些小白&#xff0c;清理C盘中的缓存&#xff0c;但是治标不治本。上正文 &#xff08;1&#xff09;打开电脑&#xff0c;输入winr &#xff08;2&#xff09;输入%temp% 该文件目录下全是缓存文件可以删除&…

2023年京东双11红包领取入口口令活动时间是从什么时候开始到几月几号结束如何领取2023京东双十一红包优惠券?

2023年京东双11红包领取活动时间是什么时候&#xff1f; 京东双11红包领取活动时间将于2023年10月23日00:00开始至11月11日23:59结束&#xff1b; 2023年京东双11红包领取入口在哪里如何天天免费领取&#xff1f; 2023年京东双11红包口令「红包到手677」&#xff0c;请在活动…

完美解决lftp遇到put: Access failed: 553 Could not create file.

目录 一、问题 二、原因 三、解决方法 一、问题 put: Access failed: 553 Could not create file. 二、原因 &#xff08;1&#xff09;没有关闭SeLinux &#xff08;2&#xff09;linux默认安装vsftp服务之后只允许匿名用户的访问和下载&#xff0c;不支持上传。 三、解决方…

【Java】nextInt()后面紧接nextLine()读取不到数据/InputMismatchException异常的解决方案

错误如下&#xff1a; 有时候还会抛出InputMismatchException异常 看&#xff01;我只输入了一个5&#xff0c;并没有给str赋值&#xff0c;它就已经将结果打印出来了&#xff01;这就意味着&#xff0c;str是读取到了数据的&#xff0c;只不过这个数据并不是我们想要的输入的…

unity ugui text 超链接和下划线,支持部分富文本格式

unity版本&#xff1a;2021.3.6f1 局限性&#xff1a; 1.测试发现不能使用 size 富文本标签, 2.同一文本不能设置不同颜色的超链接文本 其它&#xff1a;代码中注释掉使用innerTextColor的地方&#xff0c;可以使用富文本设置超链接颜色&#xff0c; 但是下划线是文本本身颜色 …

Mybatis学习笔记注解/xml映射/动态SQL%%%Mybatis教程

介绍 Mybatis 是一款优秀的持久层框架&#xff0c;用于简化 JDBC 的开发 MyBatis中文网 Mybatis 入门 快速入门 步骤 创建 SpringBoot 工程、数据库表 user、实体类 User引入 Mybatis 相关依赖&#xff0c;配置 Mybatis&#xff08;数据库连接信息&#xff09;编写 SQL 语…

adb调试Linux嵌入式设备记录

1. ADB的全称为Android Debug Bridge&#xff0c;调试设备或调试开发的Android APP。 2.adb的windows下载安装路径&#xff1a;SDK 平台工具版本说明 | Android 开发者 | Android Developers 3.linux中安装adb,参考该链接&#xff1a; https://www.cnblogs.com/androidsu…

Springboot+vue的财务管理系统(有报告),Javaee项目,springboot vue前后端分离项目。

演示视频&#xff1a; Springbootvue的财务管理系统&#xff08;有报告&#xff09;&#xff0c;Javaee项目&#xff0c;springboot vue前后端分离项目。 项目介绍&#xff1a; 本文设计了一个基于Springbootvue的前后端分离的财务管理系统&#xff0c;采用M&#xff08;model…

基于Seata的分布式事务方案

在Seata中&#xff0c;有4种分布式事务实现方案 XA、AT、TCC、Saga 其中XA利用了数据库的分布式事务特性&#xff0c;AT相当于框架去控制事务回滚。TCC手写三个方法&#xff0c;saga手写两个方法。 AT的性能和编写比较折中&#xff0c;是最常用的一种。TCC一些视频教程中介绍…

windows系统安装openssl并且转换证书格式

概述 碎碎念&#xff0c;如果你有MAC电脑&#xff0c;就别折腾了&#xff0c;直接用MAC电脑吧,不用安装直接用openssl 本文主要讲到了openssl的基本使用方法&#xff0c;开发环境为windows&#xff0c;开发工具为VS2019.本文主要是说明openssl如何使用&#xff0c;不介绍任何理…

判断某点是否在三角形内(Python)

已知三角形的三个顶点坐标&#xff0c;判断某个点是否在三角形中&#xff08;在三角形的边上&#xff0c;我们也视作在三角形中&#xff09;&#xff0c;我们提供不同的方法。 方法1&#xff1a;内角和等于360 方法2&#xff1a;等面积法 即对于△ABC内的某一点P&#xff0c;…

LInux文件权限相关知识介绍

LInux文件权限相关知识分享&#x1f60e; 前言&#x1f64c;Linux相关权限的概念&#xff1a;文件类型基本权限文件访问权限的相关设置方法chmod① 用户表示符/-权限字符②三位8进制数字 总结撒花&#x1f49e; &#x1f60e;博客昵称&#xff1a;博客小梦 &#x1f60a;最喜欢…

java+springboot+vue高校毕业生就业统计管理系统022xr

系统的设计与实现采用Spring、SpringMVC和MyBatis作为主体框架,系统设计遵循界面层、业务逻辑层和数据访问层的Web开发三层架构。采用B/S结构,使得系统更加容易维护。系统的设计与实现主要实现角色有管理员和用户,管理员在后台管理用户表模块、token表模块、生源信息模块、招聘…

代码随想录Day19 LeetCode T669修剪二叉搜索树 LeetCode T108将有序数组转化为二叉搜索树 T538 把二叉搜索树转化为累加树

LeetCode T669 修剪二叉搜索树 题目链接:669. 修剪二叉搜索树 - 力扣&#xff08;LeetCode&#xff09; 题目思路 这题我们有几个思路需要避坑,首先我们不能这样想,比如遇见比low值还小的节点值,不能直接返回null,而是考虑该节点的右子树有没有符合题目需求的节点值存在,同理删…