第三阶段-03MyBatis 中使用XML映射文件详解
MyBatis 中使用XML映射文件
什么是XML映射
使用注解的映射SQL的问题:
- 长SQL需要折行,不方便维护
- 动态SQL查询拼接复杂
- 源代码中的SQL,不方便与DBA协作
MyBatis建议使用XML文件映射SQL才能最大化发挥MySQL的功能
- 统一管理SQL, 方便协作
- 不需要 “ ” + 等语法,方便“长”SQL
- 方便处理动态SQL连接
参考连接: https://mybatis.org/mybatis-3/zh/sqlmap-xml.html
HelloWorld
开发步骤:
- 创建项目(不要使用Spring Boot 3!), 选择依赖:
-
配置application.properties, 设置数据库连接
spring.datasource.url=jdbc:mysql://localhost:3306/bootdb?characterEncoding=utf8&useSSL=false&serverTimezone=Asia/Shanghai&rewriteBatchedStatements=true spring.datasource.username=root spring.datasource.password=root# 设定 mapper xml 文件的位置, classpath 就是指 resources 位置 mybatis.mapper-locations=classpath:mappers/*.xml # 查看MyBatis执行的SQL logging.level.cn.tedu.boot2209.mapper=debug
-
创建文件夹 /resources/mappers
-
添加一个XML文件,文件从doc.canglaoshi.org 下载
-
改名为 DemoMapper.xml
<?xml version="1.0" encoding="UTF-8" ?> <!DOCTYPE mapperPUBLIC "-//mybatis.org//DTD Mapper 3.0//EN""http://mybatis.org/dtd/mybatis-3-mapper.dtd"> <!-- namespace 的值设定为被映射的包名.类名 --> <mapper namespace="cn.tedu.boot2209.mapper.DemoMapper"><!-- select 元素用于映射查询语句到方法,id值必须和mapper接口中的方法名一致!需要设定返回值类型resultType,类型与方法返回值类型一致select 元素中定义SQL,SQL查询结果将自动映射到方法返回值, 不要使用分号结尾!!--><select id="hello" resultType="java.lang.String">SELECT 'Hello World!'</select> </mapper>
-
-
创建mapper.DemoMapper接口:
- 接口名和 xml文件的namespace 一致
- 方法名和xml文件的select元素的id一致
- 方法返回值类型和 resultType 的值一致
/*** 编写Mapper接口,用于映射SQL语句*/ @Mapper public interface DemoMapper {String hello(); }
-
编写MyBatis配置文件 config.MyBatisConfig
- 包名、文件名,没有限制!
- 文件中使用 MapprScan 扫描 Mapper包:
/*** 创建一个配置文件,MyBatisConfig* 在配置文件中,启动Mapper接口扫描功能* Mapper 接口扫描功能会自动创建 Mapper接口的实现对象(使用的JDK动态代理技术)*/ @MapperScan(basePackages = "cn.tedu.boot2209.mapper") @Configuration public class MyBatisConfig { }
-
测试案例: 测试结果说明,SQL被执行了,方法返回了SQL语句的结果
@SpringBootTest public class DemoMapperTests {@AutowiredDemoMapper demoMapper;@Testvoid test(){String str = demoMapper.hello();System.out.println(str);} }
Spring Boot 中的配置类(配置文件)
@Configuration 用于声明新的配置文件类。
Spring Boot 中的主配置文件,就是Spring Boot 的启动类,可以作为配置文件使用。如果将全部配置信息放到主配置文件,就会很混乱。一般在开发中,将配置文件分开放置,相关的放到一起。
- MyBatis 放到一个文件中
- 安全配置放到一个文件中
- … …
创建一个配置包 config 管理全部的配置,然后创建MyBatis的配置类, 配置类需要标注 @Configuration
/*** 创建一个配置文件,MyBatisConfig* 在配置文件中,启动Mapper接口扫描功能* Mapper 接口扫描功能会自动创建 Mapper接口的实现对象(使用的JDK动态代理技术)*/
@MapperScan(basePackages = "cn.tedu.boot2209.mapper")
@Configuration
public class MyBatisConfig {
}
MyBatis XML映射文件工作原理
关于XML语法:
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapperPUBLIC "-//mybatis.org//DTD Mapper 3.0//EN""http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="cn.tedu.boot2209.mapper.ProductMapper"><select id="countProduct" resultType="java.lang.Integer">SELECT COUNT(*) FROM product</select>
</mapper>
- 处理节点:
<?xml version="1.0" encoding="UTF-8" ?>
从来没有变过!- 可以省略,但是不建议省略!
- 文档定义: ”DOCTYPE“ 用于约定XML文件中的 元素、属性、嵌套关系
- 可以约束标签和属性
- 标签/标记:
<mapper>
- 必须成对使用,有开启标签就必须结束标签:
<mapper></mapper>
- 必须成对使用,有开启标签就必须结束标签:
- 开始标签上可以定义属性:
id="countProduct"
- 属性名不可以重复,属性无顺序
- XML文件只能有唯一的根元素!!!
- XML 可扩展的标记语言:
- 标签可以任意名称,标签名可以扩展
- 标签嵌套关系可以扩展,标签可以任意嵌套
- 属性可以扩展
- XML 中大小写敏感,不同!
有参数的查询
处理一个参数查询
例子:
SELECT count(*) FROM product WHERE price > ?
处理多个参数查询
处理实体类型返回值
使用 Product 实体类作为返回值, 在resultType上指定实体类型就可以了
desc product;
+-------+--------------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+-------+--------------+------+-----+---------+----------------+
| id | int(11) | NO | PRI | NULL | auto_increment |
| title | varchar(50) | YES | | NULL | |
| price | double(10,2) | YES | | NULL | |
| num | int(11) | YES | | NULL | |
+-------+--------------+------+-----+---------+----------------+
定义实体类型 Product
/*** 产品实体类型*/
public class Product {private Integer id;private String title;private Double price;private Integer quantity; //数量public Product() {}public Product(Integer id, String title, Double price, Integer quantity) {this.id = id;this.title = title;this.price = price;this.quantity = quantity;}public Integer getId() {return id;}public void setId(Integer id) {this.id = id;}public String getTitle() {return title;}public void setTitle(String title) {this.title = title;}public Double getPrice() {return price;}public void setPrice(Double price) {this.price = price;}public Integer getQuantity() {return quantity;}public void setQuantity(Integer quantity) {this.quantity = quantity;}@Overridepublic String toString() {return "Product{" +"id=" + id +", title='" + title + '\'' +", price=" + price +", quantity=" + quantity +'}';}
}
编写ProductMapper接口方法
/*** 根据ID返回一个对象*/
Product findById(Integer id);
编写映射文件 ProductMapper.xml
<select id="findById" resultType="cn.tedu.boot2209.entity.Product">SELECT id, title, price, num AS quantityFROM productWHERE id = #{id}
</select>
测试:ProductMapperTests
@Test
void findById(){Product product = productMapper.findById(4);System.out.println(product);
}
返回实体集合
在ProductMapper接口中添加方法:
/*** 返回一组实体对象* @param title %手机* @return 匹配的一组对象*/
List<Product> findByTitle(String title);
在 ProductMapper.xml 添加SQL语句:
<!-- 返回一组实体对象,必须有 resultType 值是返回集合中的元素类型-->
<select id="findByTitle" resultType="cn.tedu.boot2209.entity.Product">SELECT id, title, price, num AS quantityFROM productWHERE title LIKE #{title}
</select>
测试方法 ProductMapperTests
@Test
void findByTitle(){List<Product> products = productMapper.findByTitle("%手机");for (Product product : products){System.out.println(product);}
}
插入和更新
使用变量传递参数
参数少,没有问题,但是参数多了以后就麻烦了,书写繁琐复杂
插入数据SQL:
INSERT INTO product (id, title, price, num ) VALUES (null, ?, ? ,?)
ProductMapper接口:插入、更新、删除方法只有一个默认返回int值,表示SQL影响行数
Integer saveProduct(@Param("title") String title,@Param("price") Double price,@Param("quantity") Integer quantity);
在MyBatis ProductMapper.xml:
<!-- insert 插入语句不需要定义 resultType,默认就有int返回值 -->
<insert id="saveProduct">INSERT INTO product (id, title, price, num ) VALUES (null, #{title}, #{price}, #{quantity})
</insert>
测试:ProductMapperTests
@Test
void saveProduct(){Integer n = productMapper.saveProduct("大力手机", 2000.0, 100);System.out.println(n);
}
使用POJO对象打包传递参数
POJO 就是传统Java对象,实体对象 Product 对象就是 POJO。
使用POJO对象作为Mapper方法参数: ProductMapper, 无需定义@Parm
Integer saveProductItem(Product product);
MyBatis 自动将POJO对象的属性, 映射传递到 #{占位符}
<!-- MyMatis 会自动的将 product 的属性 映射到#{title}, #{price}, #{quantity}要求 #{title}, #{price}, #{quantity} 占位符必须和 product 的属性(getXXX)一致-->
<insert id="saveProductItem">INSERT INTO product (id, title, price, num ) VALUES (null, #{title}, #{price}, #{quantity})
</insert>
测试
@Test
void saveProductItem(){Product product = new Product(null, "大力手机", 2000.0, 100);Integer n = productMapper.saveProductItem(product);System.out.println(n);
}
返回自动增加的ID
使用POJO作为参数插入数据时候,可以返回自增的ID:
- useGeneratedKeys=“true” 使用生成的key
- keyProperty=“id” key 的属性名
<!-- useGeneratedKeys="true" 使用生成的keykeyProperty="id" key 的属性名 -->
<insert id="saveProductItem" useGeneratedKeys="true" keyProperty="id">INSERT INTO product (id, title, price, num)VALUES (null, #{title}, #{price}, #{quantity})
</insert>
测试:
@Test
void saveProductItem(){Product product = new Product(null, "他的手机", 3000.0, 100);Integer n = productMapper.saveProductItem(product);System.out.println(n);System.out.println(product); //输出刚刚生成的 ID
}
更新数据 update
更新数据 SQL, 更新一行的全部数据:
UPDATE product SET title=?, price=?, num=? WHERE id=?
ProductMapper接口:
Integer updateProduct(Product product);
ProductMapper.xml:
<update id="updateProduct">UPDATE product SET title=#{title}, price=#{price}, num=#{quantity} WHERE id=#{id}
</update>
测试:
@Test
void updateProduct(){Product product = new Product(12, "老虎的手机", 100.99, 10);Integer num = productMapper.updateProduct(product);System.out.println(product);System.out.println(num);
}
MyBatis 动态SQL拼接
根据参加参数条件动态生成SQL,提示SQL效率。
动态SQL标签: if choose when for 等
/*** 动态SQL更新* @param product* @return*/
Integer updateProductPart(Product product);
XML:
<!-- 检查参数,动态拼接SQL -->
<!-- test="title != null" 检查title不为空,这拼接一段SQL title=#{title}<set> 标签会自动删除多余的逗号 -->
<update id="updateProductPart">UPDATE product<set><if test="title != null">title=#{title},</if><if test="price != null">price=#{price},</if><if test="quantity != null">num=#{quantity}</if></set>WHERE id = #{id}
</update>
测试:
@Test
void updateProductPart(){Product product = new Product(10, null, 1500.0, null);Integer num = productMapper.updateProductPart(product);System.out.println(product);System.out.println(num);//一定要检查 SQL 处理结果!不是1,就是更新失败!!
}
相关文章:

第三阶段-03MyBatis 中使用XML映射文件详解
MyBatis 中使用XML映射文件 什么是XML映射 使用注解的映射SQL的问题: 长SQL需要折行,不方便维护动态SQL查询拼接复杂源代码中的SQL,不方便与DBA协作 MyBatis建议使用XML文件映射SQL才能最大化发挥MySQL的功能 统一管理SQL, 方…...

从0开始学python -41
Python3 命名空间和作用域 命名空间 先看看官方文档的一段话: A namespace is a mapping from names to objects.Most namespaces are currently implemented as Python dictionaries。 命名空间(Namespace)是从名称到对象的映射,大部分的命名空间都是…...

如何将Google浏览器安装到D盘(内含教学视频)
如何将Google浏览器安装到D盘(内含教学视频) 教学视频下载链接地址:https://download.csdn.net/download/weixin_46411355/87503968 目录如何将Google浏览器安装到D盘(内含教学视频)教学视频下载链接地址:…...

三战阿里测试岗,成功上岸,面试才是测试员涨薪真正的拦路虎...
第一次面试阿里记得是挂在技术面上,当时也是技术不扎实,准备的不充分,面试官出的面试题确实把我问的一头雾水,还没结束我就已经知道我挂了这次面试。 第二次面试,我准备的特别充分,提前刷了半个月的面试题…...
Java代码弱点与修复之——ORM persistence error(对象关系映射持久错误)
弱点描述 ORM persistence error, ORM 持久化错误 。表示 ORM 工具在尝试将对象保存到数据库中时出现了问题。可能的原因包括: 数据库连接错误:ORM 工具无法连接到数据库,或者连接到数据库的权限不足。数据库表结构错误:ORM 工具无法正确映射对象和数据库表之间的关系,可…...

原始GAN-pytorch-生成MNIST数据集(原理)
文章目录1. GAN 《Generative Adversarial Nets》1.1 相关概念1.2 公式理解1.3 图片理解1.4 熵、交叉熵、KL散度、JS散度1.5 其他相关(正在补充!)1. GAN 《Generative Adversarial Nets》 Ian J. Goodfellow, Jean Pouget-Abadie, Yoshua Be…...

Vue下载安装步骤的详细教程(亲测有效) 1
目录 一、【准备工作】nodejs下载安装(npm环境) 1 下载安装nodejs 2 查看环境变量是否添加成功 3、验证是否安装成功 4、修改模块下载位置 (1)查看npm默认存放位置 (2)在 nodejs 安装目录下,创建 “node_global…...

[Android Studio] Android Studio生成数字证书,为应用签名
🟧🟨🟩🟦🟪 Android Debug🟧🟨🟩🟦🟪 Topic 发布安卓学习过程中遇到问题解决过程,希望我的解决方案可以对小伙伴们有帮助。 📋笔记目…...
应用IC 卡继续教育网络管理系统前后影响因素比较
3.1 实现了继续护理教育网络化管理近年来,随着一些医院继续护理教育管理信息系统的建立,有效改进了学分档案管理模式和教学模式,但这些继续护理教育管理信息系统一般为局域网,仅能达到满足自身管理的基本需求,而系统如…...

Clickhouse学习(一):MergeTree概述
MergeTree一、Clickhouse表引擎概述二、MergeTree表引擎<一>、ReplacingMergeTree引擎<二>、SummingMergeTree引擎<三>、AggregatingMergeTree引擎三、MergeTree分区一、Clickhouse表引擎概述 MergeTree表引擎:允许根据日期和主键创建索引 1、ReplacingMerge…...

Windows离线安装rust
目前rust安装常用的方式就是通过Rustup安装,此安装方式需要访问互联网。在生产环境中由于网络限制,不能直接访问互联网或者不能访问目标网站,这时候需要用离线安装的方式,本文将详细介绍离线安装步骤,并给出了vscode如…...

Android与flutter混合开发
这里我使用的android studio版本是2020.3.1;flutter版本2.5.3。此前在网上搜索的很多教教程版本都不一样,新版的IDE和SDK让我遇到了很多坑故这里整理一下。一、创建项目1.在Android项目中点击File->New->New Flutter Project。File->New->Ne…...
Linux和C语言的学习方法你真的知道吗?
★Linux的使用 第一天,就给我们讲了为什么要先学c、学linux:因为嵌入式的根本就是软件驱动硬件,而C语言是最接近硬件的语言、有指针的概念、可以直接操作硬件,另外,功能复杂的硬件是含有操作系统的,这就需…...
代码随想录day42
1049. 最后一块石头的重量 II https://leetcode.cn/problems/last-stone-weight-ii/ 这个自己还是没想出来01背包对应。 本题其实就是尽量让石头分成重量相同的两堆,相撞之后剩下的石头最小,这样就化解成01背包问题了。 stones [2,7,4,1,8,1]也就是sum…...

【笔记】两台1200PLC进行S7 通信(1)
使用两台1200系列PLC进行S7通信(入门) 文章目录 目录 文章目录 前言 一、通信 1.概念 2.PLC通信 1.串口 2.网口 …...
统一网关Gateway
为什么需要网关 网关功能: 身份认证和权限校验服务路由,负载均衡 根据请求判断找到对应的服务路由,然后服务可能有多个实例,这个时候网关就会做一个负载均衡去挑选一个实例调用.请求限流 限制请求的数量,这是微服务的…...
6、kubernetes(k8s)安装
本文内容以语雀为准 文档 等等,Docker 被 Kubernetes 弃用了?容器运行时端口和协议kubeadm initkubeadm config安装网络策略驱动使用 kubeadm 创建集群 控制平面节点隔离 持久卷为容器设置环境变量在CentOS上安装Docker引擎Pod 网络无法访问排查处理 说明 本文…...

python-批量下载某短视频平台音视频标题、评论、点赞数
python-批量下载某短视频平台音视频标题、评论数、点赞数前言一、获取单个视频信息1、获取视频 url2、发送请求3、数据解析二、批量获取数据1、批量导入地址2、批量导出excel文件3、批量存入mysql数据库三、完整代码前言 1、Cookie中文名称为小型文本文件,指某些网…...

【数据结构与算法】单链表的增删查改(附源码)
这么可爱的猫猫不值得点个赞吗😽😻 目录 一.链表的概念和结构 二.单链表的逻辑结构和物理结构 1.逻辑结构 2.物理结构 三.结构体的定义 四.增加 1.尾插 SListpushback 2.头插 SListpushfront 五.删除 1.尾删 SListpopback 2.头删 SListpo…...
华为OD机试 - 回文字符串
题目描述 如果一个字符串正读和反渎都一样(大小写敏感),则称它为一个「回文串」,例如: leVel是一个「回文串」,因为它的正读和反读都是leVel;同理a也是「回文串」art不是一个「回文串」,因为它的反读tra与正读不同Level不是一个「回文串」,因为它的反读leveL与正读不…...

使用docker在3台服务器上搭建基于redis 6.x的一主两从三台均是哨兵模式
一、环境及版本说明 如果服务器已经安装了docker,则忽略此步骤,如果没有安装,则可以按照一下方式安装: 1. 在线安装(有互联网环境): 请看我这篇文章 传送阵>> 点我查看 2. 离线安装(内网环境):请看我这篇文章 传送阵>> 点我查看 说明:假设每台服务器已…...

【Redis技术进阶之路】「原理分析系列开篇」分析客户端和服务端网络诵信交互实现(服务端执行命令请求的过程 - 初始化服务器)
服务端执行命令请求的过程 【专栏简介】【技术大纲】【专栏目标】【目标人群】1. Redis爱好者与社区成员2. 后端开发和系统架构师3. 计算机专业的本科生及研究生 初始化服务器1. 初始化服务器状态结构初始化RedisServer变量 2. 加载相关系统配置和用户配置参数定制化配置参数案…...
python如何将word的doc另存为docx
将 DOCX 文件另存为 DOCX 格式(Python 实现) 在 Python 中,你可以使用 python-docx 库来操作 Word 文档。不过需要注意的是,.doc 是旧的 Word 格式,而 .docx 是新的基于 XML 的格式。python-docx 只能处理 .docx 格式…...

九天毕昇深度学习平台 | 如何安装库?
pip install 库名 -i https://pypi.tuna.tsinghua.edu.cn/simple --user 举个例子: 报错 ModuleNotFoundError: No module named torch 那么我需要安装 torch pip install torch -i https://pypi.tuna.tsinghua.edu.cn/simple --user pip install 库名&#x…...

Aspose.PDF 限制绕过方案:Java 字节码技术实战分享(仅供学习)
Aspose.PDF 限制绕过方案:Java 字节码技术实战分享(仅供学习) 一、Aspose.PDF 简介二、说明(⚠️仅供学习与研究使用)三、技术流程总览四、准备工作1. 下载 Jar 包2. Maven 项目依赖配置 五、字节码修改实现代码&#…...

论文笔记——相干体技术在裂缝预测中的应用研究
目录 相关地震知识补充地震数据的认识地震几何属性 相干体算法定义基本原理第一代相干体技术:基于互相关的相干体技术(Correlation)第二代相干体技术:基于相似的相干体技术(Semblance)基于多道相似的相干体…...
Web中间件--tomcat学习
Web中间件–tomcat Java虚拟机详解 什么是JAVA虚拟机 Java虚拟机是一个抽象的计算机,它可以执行Java字节码。Java虚拟机是Java平台的一部分,Java平台由Java语言、Java API和Java虚拟机组成。Java虚拟机的主要作用是将Java字节码转换为机器代码&#x…...
第7篇:中间件全链路监控与 SQL 性能分析实践
7.1 章节导读 在构建数据库中间件的过程中,可观测性 和 性能分析 是保障系统稳定性与可维护性的核心能力。 特别是在复杂分布式场景中,必须做到: 🔍 追踪每一条 SQL 的生命周期(从入口到数据库执行)&#…...
【LeetCode】3309. 连接二进制表示可形成的最大数值(递归|回溯|位运算)
LeetCode 3309. 连接二进制表示可形成的最大数值(中等) 题目描述解题思路Java代码 题目描述 题目链接:LeetCode 3309. 连接二进制表示可形成的最大数值(中等) 给你一个长度为 3 的整数数组 nums。 现以某种顺序 连接…...
WEB3全栈开发——面试专业技能点P7前端与链上集成
一、Next.js技术栈 ✅ 概念介绍 Next.js 是一个基于 React 的 服务端渲染(SSR)与静态网站生成(SSG) 框架,由 Vercel 开发。它简化了构建生产级 React 应用的过程,并内置了很多特性: ✅ 文件系…...