MyBatis补充

news2024/9/20 1:06:43

控制类和dao层接口以及mapper中的xml是怎样的关联的?

在Mybatis中,控制类和dao层接口是通过mapper的xml文件进行连接的。

  1. 控制类调用dao层接口中的方法,通过接口实现进行访问数据库操作。
  2. dao层接口定义数据库操作的方法,提供给控制类调用。
  3. mapper的xml文件中定义了dao层接口中方法的具体实现,包括SQL语句的编写和参数的映射关系。
  4. 接口实现是通过Mybatis的动态代理机制实现的。Mybatis会根据接口和对应的mapper的xml文件生成接口的实现类,并在需要访问数据库时调用mapper中的SQL语句进行操作。

MyBatis动态SQL

动态 SQL 只有几个基本元素,与 JSTL 或 XML 文本处理器相似,十分简单明了,大量的判断都可以在 MyBatis 的映射 XML 文件里配置,以达到许多需要大量代码才能实现的功能。

动态 SQL 大大减少了编写代码的工作量,更体现了 MyBatis 的灵活性、高度可配置性和可维护性。

元素作用备注
if判断语句单条件分支判断
choose(when、otherwise)相当于Java中的switch case语句多条件分支判断
trim、where辅助元素用于处理一些SQL拼装问题
foreach循环语句在in语句等列举条件常用
bind辅助元素拼接参数

where 标签

where 标签主要用来简化 SQL 语句中的条件判断,可以自动处理 AND/OR 条件

if 标签

MyBatis if 类似于 Java 中的 if 语句,是 MyBatis 中最常用的判断语句。使用 if 标签可以节省许多拼接 SQL 的工作,把精力集中在 XML 的维护上。

bind 标签

bind 标签可以通过 OGNL [对象导航图语言(Object Graph Navigation Language)]表达式自定义一个上下文变量。

	<!-- resultType查出来的结果中的每一行都要映射成该类型的对象,写全称 -->
	<select id="getStaff" resultType="com.easy.bean.Staff">
		select * from staff 
		<!-- 根据参数不同组合出不同的SQL语句 动态SQL语句 标签 -->
		<where>
			<!-- 编写条件语句 如果where标签中有内容 会自动添加where关键字 -->
			<if test="checktext !=null and checktest !=''">
				<!-- 重新定义参数内容 -->
				<bind name="liketext" value="'%'+checktext+'%'"/>
				name like #{liketext}
			</if>
		</where>
	</select>

foreach 标签

foreach 标签用于循环语句,它很好的支持了数组和 List、set 接口的集合,并对此提供遍历的功能。

foreach 标签主要有以下属性

  • item:表示集合中每一个元素进行迭代时的别名。
  • index:指定一个名字,表示在迭代过程中每次迭代到的位置。
  • open:表示该语句以什么开始(既然是 in 条件语句,所以必然以(开始)。
  • separator:表示在每次进行迭代之间以什么符号作为分隔符(既然是 in 条件语句,所以必然以,作为分隔符)
  • close:表示该语句以什么结束(既然是 in 条件语句,所以必然以)结束)。
	<insert id="addList">
		insert into staff(code,name,salary,username,userpass)
		values
		<foreach collection="list" item="it" separator=",">
		(#{it.code},#{it.name},#{it.salary},#{it.username},#{it.userpass})
		</foreach>
	</insert>

注意:

使用 foreach 标签时,最关键、最容易出错的是 collection 属性,该属性是必选的,但在不同情况下该属性的值是不一样的,主要有以下 3 种情况:

  1. 如果传入的是单参数且参数类型是一个 List,collection 属性值为 list。
  2. 如果传入的是单参数且参数类型是一个 array 数组,collection 的属性值为 array。
  3. 如果传入的参数是多个,需要把它们封装成一个 Map,当然单参数也可以封装成 Map。Map 的 key 是参数名,collection 属性值是传入的 List 或 array 对象在自己封装的 Map 中的 key。

choose、when和otherwise 标签

MyBatis 中动态语句 choose-when-otherwise 类似于 Java 中的 switch-case-default 语句。由于 MyBatis 并没有为 if 提供对应的 else 标签,如果想要达到<if>...<else>...</else> </if> 的效果,可以借助 <choose>、<when>、<otherwise> 来实现。

当判断条件中有字符串时,比较用双等号,里面的字符串用双引号,外面用单引号。

在xml文件中,尖括号<>有特殊含义,小于号用 &lt; 替换,大于号用 &gt; 替换

	<select id="getStaffBySalary" resultType="com.easy.bean.Staff">
		select * from staff
		<where>
			<!-- 参数名 salarytext -->
			<choose>
				<when test='salarytext == "低"'>
					<!-- 用&lt表示小于号,用&gt表示大于号 -->
					salary &lt;= 5000
				</when>
				<when test='salarytext == "中"'>
					salary &gt;5000 and salary &lt;=8000
				</when>
				<otherwise>
					salary &gt;8000
				</otherwise>
			</choose>
		</where>
	</select>

set 标签

在 Mybatis 中,update 语句可以使用 set 标签动态更新列。set 标签可以为 SQL 语句动态的添加 set 关键字,剔除追加到条件末尾多余的逗号。

    <update id="editStaffItem">
		update staff
		<set>
			<!-- set标签会去除多余的逗号 -->
			<if test='name!=null and name!=""'>
				name=#{name},
			</if>
			<if test="salary!=null">
				salary=#{salary},
			</if>
		</set>
		<where>
			<!-- where标签会去除多余的and,or -->
			id=#{id}
		</where>
	</update>

trim 标签

trim 一般用于去除 SQL 语句中多余的 AND 关键字、逗号,或者给 SQL 语句前拼接 where、set 等后缀,可用于选择性插入、更新、删除或者条件查询等操作。

这种效果和where相同,where本身已经可以做到去除多余的and,or的功能。


resultMap元素

resultMap 是 MyBatis 中最复杂的元素,主要用于解决实体类属性名与数据库表中字段名不一致的情况,可以将查询结果映射成实体对象。

为了使数据库的查询结果和返回值类型中的属性能够自动匹配,通常会对 MySQL 数据库和 JavaBean 采用同一套命名规则,即 Java 命名驼峰规则,这样就不需要再做映射了(数据库表字段名和属性名不一致时需要手动映射)。

一对一关联查询

通过 <resultMap> 元素的子元素 <association> 处理一对一级联关系

<association> 元素中通常使用以下属性。

  • property:指定映射到实体类的对象属性。
  • column:指定表中对应的字段(即查询返回的列名)
  • javaType:指定映射到实体对象属性的类型。
  • select:指定引入嵌套查询的子 SQL 语句,该属性用于关联映射中的嵌套查询。

查询员工及其部门,根据id将部门id子查询的结果映射到员工类Staff的部门属性dep上:

	<resultMap id="staffAndDep" type="com.easy.bean.Staff">
		<association column="dep_id" select="getStaffDep" property="dep"></association>
	</resultMap>
	
	<select id="getStaffDep" resultType="com.easy.bean.Department">
	select * from department where id=#{dep_id}
	</select>
	
	<!-- 一对一查询或一对多查询需要指定映射方式 resultMap -->
	<select id="getStaffAndDep" resultMap="staffAndDep">
		select * from staff
	</select>

控制类的方法:

	@GetMapping("staff/dep")
	public CommonResult getStaffAndDep() {
		List<Staff> lists = dao.getStaffAndDep();
		return CommonResult.success(lists);
	}

数据访问层接口:

    List<Staff> getStaffAndDep();


一对多关联查询

通过 <resultMap> 元素的子元素 <collection> 处理一对多级联关系,collection 可以将关联查询的多条记录映射到一个 list 集合属性中。

查询部门及其下的员工信息,根据id将查询结果映射到部门类的员工列表里:

	<resultMap id="departmentAndStaff" type="com.easy.bean.Department">
    <!-- <id column="id" property="depid"></id>
		<result column="name" property="depname"></result> -->
		<result column="id" property="id"></result>
		<collection fetchType="lazy" column="id" select="getDepStaff" property="staffList"></collection>
	</resultMap>
	
	<select id="getDepStaff" resultType="com.easy.bean.Staff">
		select * from staff where dep_id=#{id}
	</select>

result 标签中的内容确保了id列被映射到Department对象的id属性上,如果result不指定id,系统会将id用于子查询的映射而不进行封装,导致最后id属性为默认值0

控制类方法:

	@GetMapping("dep")
	//@Transactional
	public CommonResult getDep() {
		List<Department> list=departmentDao.getDep();
		return CommonResult.success(list);
	}

数据访问层接口:

	List<Department> getDep();

resultType和resultMap的区别:

MyBatis 的每一个查询映射的返回类型都是 resultMap,只是当我们提供的返回类型是 resultType 时,MyBatis 会自动把对应的值赋给 resultType 所指定对象的属性,而当我们提供的返回类型是 resultMap 时,MyBatis 会将数据库中的列数据复制到对象的相应属性上,可用于复制查询。


MyBatis缓存

MyBatis 提供了一级缓存和二级缓存的支持。默认情况下,MyBatis 只开启一级缓存

一级缓存

  • 一级缓存是基于 PerpetualCache(MyBatis自带)的 HashMap 本地缓存,作用范围为 SQLession 域内。当 session flush(刷新)或者 close(关闭)之后,该 session 中所有的 cache(缓存)就会被清空。
  • 在参数和 SQL 完全一样的情况下,我们使用同一个 SqlSession 对象调用同一个 mapper 的方法,往往只执行一次 SQL。因为使用 SqlSession 第一次查询后,MyBatis 会将其放在缓存中,再次查询时,如果没有刷新,并且缓存没有超时的情况下,SqlSession 会取出当前缓存的数据,而不会再次发送 SQL 到数据库。
  • 在参数和 SQL 完全一样的情况下,我们使用同一个 SqlSession 对象调用同一个 mapper 的方法,往往只执行一次 SQL。因为使用 SqlSession 第一次查询后,MyBatis 会将其放在缓存中,再次查询时,如果没有刷新,并且缓存没有超时的情况下,SqlSession 会取出当前缓存的数据,而不会再次发送 SQL 到数据库。

@Transactional 注解是用于标记在方法或类上的注解,可以声明一个事务的边界。当方法或类被@Transactional注解标记时,Spring会自动为其创建一个事务,并在方法执行前开启事务、执行方法体、执行成功后提交事务,或在遇到异常时进行回滚。

	@GetMapping("dep")
	@Transactional
	public CommonResult getDep() {
		List<Department> list=departmentDao.getDep();
		System.out.println("-------------");
		list=departmentDao.getDep();
		return CommonResult.success();
	}

在启动类上使用 @EnableTransactionManagement 注解用于开启Spring的声明式事务管理。

@SpringBootApplication
@EnableTransactionManagement
public class EasySpringApplication {
	public static void main(String[] args) {
		SpringApplication.run(EasySpringApplication.class, args);
	}
}

通过两个事务相关的注解确保两次方法调用在同一个SqlSession中,验证一级缓存:

通过日志可以看到,两次调用方法只执行了一次SQL语句。


二级缓存

二级缓存是全局缓存,作用域超出 SQLsession 范围之外,可以被所有 SqlSession 共享。手动开启

在mapper的xml文件中使用以下语句开启二级缓存:

	<cache eviction="FIFO" flushInterval="60000" size="512" readOnly="true" />

二级缓存要求参与的对象都是可序列化的,实现Serializable接口。

测试代码:

	@GetMapping("dep")
	public CommonResult getDep() {
		List<Department> list=departmentDao.getDep();
		System.out.println("-------------");
		list=departmentDao.getDep();
		return CommonResult.success();
	}

从日志可见:二级缓存已生效。


懒加载

MyBatis的懒加载是一种延迟加载机制,允许在需要时才加载关联对象的属性。默认情况下,MyBatis使用的是立即加载,即在执行查询语句时,同时加载关联对象的属性。但在某些情况下,如果查询结果中包含了大量的关联对象,且这些关联对象可能在业务逻辑中并不总是需要的,这时懒加载就能提高查询性能和减少内存消耗

懒加载可以在以下两种场景中使用:

  1. 延迟加载关联对象:当你在查询对象时,并不立即加载关联对象的属性,只有在真正访问关联对象的属性时,才会执行额外的查询语句来加载关联对象的数据。

  2. 延迟加载集合属性:当你查询对象并包含有关联的集合属性时,仅在访问这些集合属性时才会执行额外的查询语句来加载集合属性中的数据。

懒加载在 collection 标签中设置属性 fetchType="lazy"

fetchType用于控制数据库查询时关联对象的加载时机和方式。它决定了是在查询主对象时立即加载关联对象(迫切加载),还是在访问关联对象时才从数据库中加载(懒加载)。

	<resultMap id="departmentAndStaff" type="com.easy.bean.Department">
		<result column="id" property="id"></result>
		<collection fetchType="lazy" column="id" select="getDepStaff" property="staffList"></collection>
	</resultMap>
	
	<select id="getDepStaff" resultType="com.easy.bean.Staff">
		select * from staff where dep_id=#{id}
	</select>
	
	<select id="getDep" resultMap="departmentAndStaff">
		select * from department
	</select>

测试代码:

	@GetMapping("dep")
	public CommonResult getDep() {
		List<Department> list=departmentDao.getDep();
		System.out.println("-------------");
		System.out.println(list.get(0));
		System.out.println(list.get(1));
		return CommonResult.success();
	}

从日志中可见:在方法刚调用时仅执行了 select * from department 并没有立即进行子查询,

当方法访问到集合元素 list.get(0) 和 list.get(1) 时,子查询语句才分别执行。

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

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

相关文章

第6章>>实验7:PS(ARM)端Linux RT与PL端FPGA之间(通过Memory存储器进行通信和交互)《LabVIEW ZYNQ FPGA宝典》

1、实验内容 上一节实验里面介绍的Reg寄存器通道比较适合在PS端和PL端之间传递标量数据&#xff0c;也就是单个元素&#xff0c;如果要传递多个元素的数组或者连续数据流的话&#xff0c;Reg寄存器通道就不是很合适了。 本节实验我们向大家讲解如何借助Memory存储器通道在PS&am…

【Mind+】掌控板入门教程06 多彩呼吸灯

呼吸灯是指模仿动物一呼一吸使灯光由亮到暗逐渐变化&#xff0c;给人以安静沉稳的感觉。电子产品中经常会使用不同色彩的呼吸灯&#xff0c;起到很好的视觉提醒效果。 这个项目中我们将带领大家用掌控板制作一个颜色和亮度一起变化的多彩呼吸灯&#xff01; 项目示例 …

编程深水区之并发④:Web多线程

Node的灵感来源于Chrome&#xff0c;更是移植了V8引擎。在Node中能够实现的多线程&#xff0c;在Web环境中自然也可以。 一、浏览器是多进程和多线程的复杂应用 在本系列的第二章节&#xff0c;有提到现代浏览器是一个多进程和多线程的复杂应用。浏览器主进程统管全局&#xf…

vue动态规则

vue动态规则 在Vue中&#xff0c;可以使用动态规则来实现灵活的表单验证和输入限制。动态规则允许你根据特定条件或动态数据来定义验证规则。 以下是一个示例&#xff0c;展示如何在Vue中使用动态规则&#xff1a; <template><div><input v-model"inputVa…

LVS--DR模式

目录 1 DR模式原理 2 DR模式请求回复过程 3 实验环境 4 开始实验 4.1 配置实验环境 4.2 Router 配置路由转发 4.3 LVS 设置转发规则 4.4 解决vip响应问题 4.5 Web1配置 4.6 Web2配置 5 测试效果 1 DR模式原理 当用户向负载均衡调度器&#xff08;Director Server&#xff09;发…

如何用数字便签管理工作任务?

在快节奏的工作环境中&#xff0c;我们每天都需要处理大量的工作任务。如果仅仅依靠个人的记忆力和精力&#xff0c;很容易导致任务遗漏或者延误。随着数字化技术的发展&#xff0c;选择一款功能强大的数字便签软件已经成为我们管理工作任务的更好选择。 在众多的数字便签软件…

Java零基础之多线程篇:讲解并发集合

哈喽&#xff0c;各位小伙伴们&#xff0c;你们好呀&#xff0c;我是喵手。运营社区&#xff1a;C站/掘金/腾讯云&#xff1b;欢迎大家常来逛逛 今天我要给大家分享一些自己日常学习到的一些知识点&#xff0c;并以文字的形式跟大家一起交流&#xff0c;互相学习&#xff0c;一…

c语言11天笔记

函数的概述 函数&#xff1a;实现一定功能的&#xff0c;独立的代码模块。我们的函数一定是先定义&#xff0c;后使用。 使用函数的优势&#xff1a; 1. 我们可以通过函数提供功能给别人使用。当然我们也可以使用别人提供的函数&#xff0c;减少代码量。 2. 借助函数可以减…

4.6.长短期记忆网络(LSTM)

长短期记忆网络(LSTM) ​ 长短期记忆网络的设计灵感来自于计算机的逻辑门。 长短期记忆网络引入了记忆元&#xff08;memory cell&#xff09;&#xff0c;或简称为单元&#xff08;cell&#xff09;。 有些文献认为记忆元是隐状态的一种特殊类型&#xff0c; 它们与隐状态具有…

萱仔求职系列——1.1 机器学习基础知识复习

由于我最近拿到offer还是想再找找更好的机会&#xff0c;目前有很多的面试&#xff0c;面试的时候很多面试官会问一些机器学习的基础知识&#xff0c;由于我上一段实习的时候主要是机器学习和部分深度学习的内容&#xff0c;为了避免在面试的时候想不起来自己学习的内容&#x…

MPU6050的STM32数据读取

目录 1. 概述2. STM32G030对MPU6050的读取3. STM32F1xx对MPU6050的读取 1. 概述 项目中&#xff0c;往往需要根据不同的环境使用不同的芯片处理某些数据&#xff0c;当使用不同的芯片对六轴陀螺仪芯片MPU6050进行数据处理中&#xff0c;硬件的连接、I/O口的设置往往需要根据相…

【HarmonyOS NEXT星河版开发学习】小型测试案例05-得物列表项

个人主页→VON 收录专栏→鸿蒙开发小型案例总结​​​​​ 基础语法部分会发布于github 和 gitee上面&#xff08;暂未发布&#xff09; 前言 鸿蒙操作系统通过其先进的分布式架构和开发工具&#xff0c;以及灵活的界面布局和样式控制&#xff0c;为开发者提供了丰富的开发资源…

设计模式- 数据源架构模式

活动记录&#xff08;Active Record&#xff09; 一个对象&#xff0c;它包装数据库表或视图中的某一行&#xff0c;封装数据库访问&#xff0c;并在这些数据上增加了领域逻辑 对象中既有数据又有行为。这些数据大多是持久数据、并且需要保存到数据库。 运行机制 活动记录的…

Iris for mac 好用的录屏软件

Iris 是一款高性能屏幕录像机&#xff0c;可录制到 h.264。Iris 在可用时利用板载 GPU 加速。它可以选择包括来自摄像头和最多两个麦克风的视频。 兼容性 所有功能在macOS 11.0-14上完全支持&#xff0c;包括macOS Sonoma。 简单编码 直接录制为h.264、h.265、ProRes或Motion…

WPF学习(10)-Label标签+TextBlock文字块+TextBox文本框+RichTextBox富文本框

Label标签 Label控件继承于ContentControl控件&#xff0c;它是一个文本标签&#xff0c;如果您想修改它的标签内容&#xff0c;请设置Content属性。我们曾提过ContentControl的Content属性是object类型&#xff0c;意味着Label的Content也是可以设置为任意的引用类型的。 案…

游戏ID统一管理器DEMO

一般游戏的角色ID、名字&#xff0c;工会ID、名字&#xff0c;等最好统一创建&#xff0c;方便合服处理&#xff0c;可以以此基础&#xff0c;动态配置生成ID 这个也可以用openresty 作个&#xff0c;可能更专业点&#xff0c; 1&#xff1a;go1.20 最后一版支持win7的 mongod…

微信小程序乡村医疗系统,源码、部署+讲解

目录 摘 要 Abstract 1 绪论 1.1 研究背景及意义 1.2 研究现状 1.3 研究内容 2 相关技术介绍 2.1 Java 语言 2.2 MySQL 数据库 2.3 Spring Boot 框架 2.4 B/S 结构 2.5 微信小程序 3 系统分析 3.1 可行性分析 3.1.1 经济可行性 3.1.2 技术可行性…

4.MySQL数据类型

目录 数据类型 ​编辑数值类型 tinyint类型 bit类型 float类型 decimal类型 字符串类型 char类型 varchar varchar和char的区别 日期和时间类型 数据类型 数值类型 说明一下&#xff1a;MySQL本身是不支持bool类型的&#xff0c;当把一个数据设置成bool类型时&#x…

【ThreadLocal总结】

文章目录 为什么使用ThreadLocalThreadLocal核心ThreadLocal内部结构ThreadLocal内存泄漏解决内存泄漏 为什么使用ThreadLocal 在并发编程中&#xff0c;多个线程同时访问和修改共享变量是一个常见的场景。这种情况下&#xff0c;可能会出现线程安全问题&#xff0c;即多个线程…

AWS生成式AI项目的全生命周期管理

随着人工智能技术的迅速发展&#xff0c;生成式 AI 已成为当今最具创新性和影响力的领域之一。生成式 AI 能够创建新的内容&#xff0c;如文本、图像、音频等&#xff0c;具有广泛的应用前景&#xff0c;如自然语言处理、计算机视觉、创意设计等。然而&#xff0c;构建一个成功…