mybatis的resultMap用法

article/2025/10/7 8:00:44

目录

1.前言

2.准备工作

2.1 类型别名

2.2 列名和属性名

2.3 mybatis映射文件处理特殊字符

2.4 sql片段

2.5 mybatis完成模糊查询

3.结果映射(resultMap)

4. 联表查询

4.1 一对一关联association

4.2 一对多关联collection

5.鉴别器


1.前言

resultMap元素是 MyBatis 中最重要最强大的元素。MyBatis 创建时的一个思想是:数据库不可能永远是你所想或所需的那个样子。 我们希望每个数据库都具备良好的第三范式或 BCNF 范式,可惜它们并不都是那样。 如果能有一种数据库映射模式,完美适配所有的应用程序,那就太好了,但可惜也没有。 而 ResultMap 就是 MyBatis 对这个问题的答案。

2.准备工作

2.1 类型别名

        代码中会出现大量重复,为了节省时间及空间,类型别名是好帮手。使用它们,就可以不用输入类的全限定名了。在mybatis的全局变量文件config.xml中填写。

 <typeAliases>
        <!--单独为某个实体类起别名, alias别名,下边使用这个别名-->
         <typeAlias type="com.qy151wd.entity.User" alias="u"/>
        <!--为指定包下的实体类起别名该别名就是实体类名-->
         <package name="com.qy151wd.entity"/>
    </typeAliases>

2.2 列名和属性名

可以有两种解决办法:

第一种: 为查询的列起别名,而别名和属性名一致。

<!--根据id查询学生信息--><select id="findOne" resultType="com.qy151wd.entity.Student">select stu_id id,stu_name name,stu_age age from tb_stu where stu_id=#{id}</select>

 第二种: 使用resultMap完成列和属性之间的映射关系。

<resultMap id="StuMapper" type="com.qy151wd.entity.Student"><!--主键的映射关系 column:列名(数据库列名) property:属性名(与实体类类名一致)--><id column="stu_id" property="id"/><!--普通列的映射关系--><result column="stu_name" property="name"/><result column="stu_age" property="age"/></resultMap><!--resultType和ResultMap二者只能用一个--><select id="findOne" resultMap="StuMapper">select * from tb_stu where stu_id=#{id}</select>

2.3 mybatis映射文件处理特殊字符

        共有两种方法,建议使用第二种:
            第一种:转义标签 &nbsp; &lt;  
            第二种: <![CDATA[sql]]>

<select id="findByMaxMin" resultType="com.qy151wd.entity.Account"><![CDATA[select * from account where id >#{min} and id <#{max}]]></select>

2.4 sql片段

在执行查询语句时不建议使用select *,建议把查询的列写出。

2.5 mybatis完成模糊查询

select * from 表名 where 列名 like '%a%'

(1)使用字符串函数 完成拼接 concat

<select id="findByLike" resultType="com.qy151wd.entity.Account">select * from account where name like concat('%',#{name},'%')</select>

 (2) 使用${}

<select id="findByLike" resultType="com.qy151wd.entity.Account">select * from account where name like '%${name}%'</select>

        区别:发现使用${}实际上是字符串拼接,它不能防止sql注入, 而#{}它是预编译,它可以防止sql注入问题,#{}实际使用的PreparedStatement.

3.结果映射(resultMap)

4. 联表查询

4.1 一对一关联association

property映射到列结果的字段或属性。如果用来匹配的 JavaBean 存在给定名字的属性,那么它将会被使用。否则 MyBatis 将会寻找给定名称的字段。 无论是哪一种情形,你都可以使用通常的点式分隔形式进行复杂属性导航。 比如,你可以这样映射一些简单的东西:“username”,或者映射到一些复杂的东西上:“address.street.number”。
javaType一个 Java 类的完全限定名,或一个类型别名(关于内置的类型别名,可以参考上面的表格)。 如果你映射到一个 JavaBean,MyBatis 通常可以推断类型。然而,如果你映射到的是 HashMap,那么你应该明确地指定 javaType 来保证行为与期望的相一致。
jdbcTypeJDBC 类型,所支持的 JDBC 类型参见这个表格之前的“支持的 JDBC 类型”。 只需要在可能执行插入、更新和删除的且允许空值的列上指定 JDBC 类型。这是 JDBC 的要求而非 MyBatis 的要求。如果你直接面向 JDBC 编程,你需要对可能存在空值的列指定这个类型。

实体类演示

//班级对象
@Data
@AllArgsConstructor
@NoArgsConstructor
public class Clazz {private int cId;private String cName;private int teacherId;
//把教师对象当作属性private Teacher teacher;
}
//教师对象
@Data
@AllArgsConstructor
@NoArgsConstructor
public class Teacher {private int tId;private String tName;
}

xml演示


<resultMap id="ClassResultMap" type="com.qy151wd.entity.Clazz">
<!-- 主键  property为实体类属性 column为数据库字段 jdbcType为实体类对应的jdbc类型此处没有使用--><id property="cId" column="c_id"/><!-- 普通属性  property为实体类属性 column为数据库字段--><result property="cName" column="c_name"/><result property="teacherId" column="teacher_id"/><!--property:teacher Clazz里面Teacher teacher  column:数据库中teacher表的对应的列名--><!--一对一映射association property 为实体类Clazz中的属性名字 javaType为实体类属性的类型 --><association property="teacher" column="teacher_id" javaType="com.qy151wd.entity.Teacher"><id property="tId" column="t_id"/><result property="tName" column="t_name"/></association></resultMap>

        若sql片段中起了别名,column就变成了这个别名,因为是临时表 。

4.2 一对多关联collection

一个班级(Clazz)只有一个教师(Teacher)。但一个班级有很多学生(Student)。像下面这样,映射嵌套结果集合到一个 List 中,可以使用集合元素。 和关联元素一样,我们可以使用嵌套 Select 查询,或基于连接的嵌套结果映射集合。 在班级类中,这可以用下面的写法来表示:

//学生类
public class Student {
private int id;
private String name;
}
//班级类
public class Clazz {
private int id;
private String name;
private Teacher teacher;
//学生类的集合的引用
private List<Student> students;
}

如何使用嵌套 Select 查询(两种方式)来为班级加载学生

<!--
方式一: 嵌套结果: 使用嵌套结果映射来处理重复的联合结果的子集
SELECT * FROM class c, teacher t,student s WHERE c.teacher_id=t.t_id AND c.C_id=s.class_id
AND c.c_id=1
-->
<!-- parameterType:输入类型 resultMap:输出结果类型-->
<select id="getClass" parameterType="int" resultMap="ClassResult">
select * from class c, teacher t,student s where c.teacher_id=t.t_id and c.C_id=s.class_id and
c.c_id=#{id}
</select><resultMap type="com.qy151wd.entity.Clazz" id="ClassResult">
<id property="id" column="c_id"/>
<result property="name" column="c_name"/>
<!--教师类查询-->
<association property="teacher" column="teacher_id"                                                                                                                  javaType="com.qy151wd.entity.Teacher">
<id property="id" column="t_id"/>
<result property="name" column="t_name"/>
</association>
<!--教学生类集合查询-->
<!-- ofType 指定 students 集合中的对象类型 -->
<collection property="students" ofType="com.qy151wd.entity.Student">
<id property="id" column="s_id"/>
<result property="name" column="s_name"/>
</collection></resultMap>
<!--
方式二:嵌套查询:通过执行另外一个 SQL 映射语句来返回预期的复杂类型
SELECT * FROM class WHERE c_id=1;
SELECT * FROM teacher WHERE t_id=1 //1 是上一个查询得到的 teacher_id 的值
SELECT * FROM student WHERE class_id=1 //1 是第一个查询得到的 c_id 字段的值
-->
<resultMap id="ClassResultMap" type="com.qy151wd.entity.Clazz"><id property="cId" column="c_id"/><result property="cName" column="c_name"/><result property="teacherId" column="teacher_id"/><!--property:teacher Clazz里面Teacher teacher column:数据库中teacher表的对应的列名--><association property="teacher" column="teacher_id" javaType="com.qy151wd.entity.Teacher"><id property="tId" column="t_id"/><result property="tName" column="t_name"/></association><!--column="c_id":根据班级的外键Id去寻找班级的学生 property="students":与Clazz类中的Student集合对应--><collection property="students" ofType="com.qy151wd.entity.Student" column="c_id"select="getStudent"></collection></resultMap><!--此处随意命名 下边引用 省略*的内容--><sql id="refiledId">c_id,c_name,teacher_id,t_id,t_name</sql>
<!--此处resultMap有是因为下面的select是它的子查询--><select id="getClazz" resultMap="ClassResultMap" parameterType="int">select <include refid="refiledId"/>  from class c join teacher t on c.teacher_id=t.t_id where c.teacher_id=#{id}</select>
<!--此处不用resultMap原因是因为select调用,因此会有输出结果类型--><select id="getStudent" parameterType="int" resultType="com.qy151wd.entity.Student">SELECT s_id sId,s_name sName,class_id classId FROM student3 WHERE class_id=#{id}</select>

 测试类

//ClassMapper接口内
public interface ClassMapper {public Clazz getClazz(int id);
}
//测试类
public class UserTest {
SqlSession sqlSession;UserMapper mapper;ClassMapper mapper1;{try{Reader reader= Resources.getResourceAsReader("conf.xml");SqlSessionFactory sqlSessionFactory=new SqlSessionFactoryBuilder().build(reader);sqlSession=sqlSessionFactory.openSession();mapper = sqlSession.getMapper(UserMapper.class);mapper1 = sqlSession.getMapper(ClassMapper.class);}catch(Exception e){e.printStackTrace();}}@Testpublic void testLianBiao(){Clazz clazz = mapper1.getClazz(1);System.out.println(clazz);}
}

5.鉴别器

        有时候,一个数据库查询可能会返回多个不同的结果集(但总体上还是有一定的联系的)。 鉴别器(discriminator)元素就是被设计来应对这种情况的,另外也能处理其它情况,例如类的继承层次结构。 鉴别器的概念很好理解——它很像 Java 语言中的 switch 语句。一个鉴别器的定义需要指定 column 和 javaType 属性。column 指定了 MyBatis 查询被比较值的地方。 而 javaType 用来确保使用正确的相等测试(虽然很多情况下字符串的相等测试都可以工作)。

<discriminator javaType="int" column="draft"><case value="1" resultType="DraftPost"/>
</discriminator>

例子

<resultMap id="vehicleResult" type="Vehicle"><id property="id" column="id" /><result property="vin" column="vin"/><result property="year" column="year"/><result property="make" column="make"/><result property="model" column="model"/><result property="color" column="color"/>
<!--javaType:这一属性在java段中代表的属性为int类型--><discriminator javaType="int" column="vehicle_type"><case value="1" resultType="carResult"><result property="doorCount" column="door_count" /></case><case value="2" resultType="truckResult"><result property="boxSize" column="box_size" /><result property="extendedCab" column="extended_cab" /></case><case value="3" resultType="vanResult"><result property="powerSlidingDoor" column="power_sliding_door" /></case><case value="4" resultType="suvResult"><result property="allWheelDrive" column="all_wheel_drive" /></case></discriminator>
</resultMap>


http://chatgpt.dhexx.cn/article/Ge9TH70a.shtml

相关文章

mybatis中resultMap的理解

resultMap 元素是 MyBatis 中最重要最强大的元素。它可以让你从 90% 的 JDBC ResultSets 数据提取代码中解放出来, 并在一些情形下允许你做一些 JDBC 不支持的事情。 实际上&#xff0c;在对复杂语句进行联合映射的时候&#xff0c;它很可能可以代替数千行的同等功能的代码。 R…

resultmap的用法

MyBatis中在查询进行select映射的时候&#xff0c;返回类型可以用resultType&#xff0c;也可以用resultMap&#xff0c;resultType是直接表示返回类型的&#xff0c;而resultMap则是对外部ResultMap的引用&#xff0c;但是resultType跟resultMap不能同时存在。在MyBatis进行查…

mybatis中resultMap配置细则

关注公众号【江南一点雨】&#xff0c;专注于 Spring Boot微服务以及前后端分离等全栈技术&#xff0c;定期视频教程分享&#xff0c;关注后回复 Java &#xff0c;领取松哥为你精心准备的 Java 干货&#xff01; resultMap算是mybatis映射器中最复杂的一个节点了&#xff0c;能…

深度解析resultMap标签

一般来说&#xff0c;一张表对应一份mapper映射文件&#xff0c;但部分属性在数据库中的存储并非直接存储其内容&#xff0c;而是存储其唯一标识&#xff0c;比如id&#xff0c;如下表中的员工政治面貌、部门、职级、岗位均是通过各个分表的id进行维护&#xff1a; 因此&#x…

ResultType和ResultMap的区别

ResultType和ResultMap都是执行查询语句时返回的结果集 ResultType ResultType相对与ResultMap而言更简单一点。只有满足ORM&#xff08;Object Relational Mapping&#xff0c;对象关系映射&#xff09;时&#xff0c;即数据库表中的字段名和实体类中的属性完全一致时&#x…

resultMap的用法以及关联结果集映射

resultType resultType可以把查询结果封装到pojo类型中&#xff0c;但必须pojo类的属性名和查询到的数据库表的字段名一致。 如果sql查询到的字段与pojo的属性名不一致&#xff0c;则需要使用resultMap将字段名和属性名对应起来&#xff0c;进行手动配置封装&#xff0c;将结…

[MyBatis]-resultMap结果映射集详解

resultMap结果映射集详解 resultmap是mybatis中最复杂的元素之一&#xff0c;它描述如何从结果集中加载对象&#xff0c;主要作用是定义映射规则、级联的更新、定制类型转化器。 resultmap构成元素 元素子元素作用constructoridArg 、arg用于配置构造器方法id将结果集标记为id…

MyBatis中ResultMap详解

简介&#xff1a; MyBatis的每一个查询映射的返回类型都是ResultMap&#xff0c;只是当我们提供的返回类型属性是resultType的时候&#xff0c;MyBatis会自动的给我们把对应的值赋给resultType所指定对象的属性&#xff0c;而当我们提供的返回类型是resultMap的时候&#xff0…

MyBatis多表查询resultMap设定

提示&#xff1a;文章写完后&#xff0c;目录可以自动生成&#xff0c;如何生成可参考右边的帮助文档 文章目录 Result Maps 是什么 ResultMap 属性 一、Java数据访问接口 二、XML实现 1、*分步查询 延迟加载 三、Test 1.读入数据 总结 Result Maps 是什么 resultMap 元素是 M…

JS字符串替换指定字符

碰到一个后端数据同步过来的xml文本段&#xff0c;内容里写死的宽度 在1920*1080的分辨率屏幕上&#xff0c;显示有问题&#xff0c;由于数据量太多&#xff0c;前端单独拿数据再处理一遍 RegExp方法&#xff1a; function replaceAll(str, find, replace) {return str.repla…

shell内置字符串替换

shell变量赋值语法&#xff1a; 使用规则解释单引号所见即所得&#xff0c;即输出时会将单引号内的所有內容都原样输出&#xff0c;或者描述为单引号里面看到的是什么就会输出什么&#xff0c;这称为强引用双引号 (默认)输出双引号内的所有内容&#xff1b;如果内容中有命令(…

python字符串替换

str.replace(old, new[, max]) 参数 old – 将被替换的子字符串。 new – 新字符串&#xff0c;用于替换old子字符串。 max – 可选字符串, 替换不超过 max 次 返回值 返回字符串中的 old&#xff08;旧字符串&#xff09; 替换成 new(新字符串)后生成的新字符串&#xff0c;如…

C++ 字符串替换

好久没有更新了&#xff0c;最近有点忙&#xff0c;今天抽点时间给大家水 写一篇关于替换字符串字符的文章 替换函数 string类型的字符串可以用swap函数来替换字符&#xff0c;例如&#xff1a; 冒泡排序 #include <bits/stdc.h> using namespace std;int main () {i…

Python字符串替换方法replace

字符串替换方法replace str1 .replace(old_str&#xff0c;new_str&#xff0c;count)字符串的替换&#xff0c;将str1中的 old_str 替换成new_str old_str:将要被替换的字符串 new_str:新的字符串&#xff0c;替换成的字符串# count:替换的次数,默认是全部替换 返回值:得到一个…

Java字符串替换的方法

java中字符串替换方法主要有三种&#xff0c;分别是replace()、replaceAll()和replaceFirst()&#xff0c;这三种方法可以在三种不同情况应用&#xff0c;下面就由我来具体说明这三种方法的应用情况吧。 replace() replace的参数是char和CharSequence&#xff0c;即可以支持字…

sed 字符串替换

1. sed替换的基本语法为: sed s/原字符串/替换字符串/ 单引号里面,s表示替换,三根斜线中间是替换的样式,特殊字符需要使用反斜线”\”进行转义。 2. 单引号” ‘ ’”是没有办法用反斜线”\”转义的,这时候只要把命令中的单引号改为双引号就行了,格式如下&#xff1a; # 要…

字符串的替换

一、字符串“打劫&#xff01;我有枪”&#xff0c;“枪”是敏感词汇&#xff0c;替换为“*”&#xff0c;并输出打印 二、字符串“北京欢迎你”&#xff0c;替换字符为“郑州欢迎你们”&#xff0c;并输出打印 package work.twelve;/* 一、字符串“打劫&#xff01;我有枪”…

两种字符串替换的方法

1.语法&#xff1a; public String replace(CharSequence target,CharSquence replacement) 注&#xff1a;旧字符换成新字符 示例&#xff1a;店小二在菜单上写下一个馒头一文&#xff0c;“一个”二字容易被他人添上一笔变成“十个”&#xff0c;于是决定把“一”替换成汉字…

7-8 字符串替换 (15 分)

7-8 字符串替换 &#xff08;15 分&#xff09; 本题要求编写程序&#xff0c;将给定字符串中的大写英文字母按以下对应规则替换&#xff1a; 输入格式&#xff1a; 输入在一行中给出一个不超过80个字符、并以回车结束的字符串。 输出格式&#xff1a; 输出在一行中给出替…

全网最全Spring面试题之高级篇整理总结(共25题,附超详细解答)

1、什么是 Spring 框架&#xff1f;Spring 框架有哪些主要模块&#xff1f; Spring 框架是一个为 Java 应用程序的开发提供了综合、广泛的基础性支持的 Java 平台。Spring 帮助开发者解决了开发中基础性的问题&#xff0c;使得开发人员可以专注于应用程序的开发。 Spring 框架本…