第三阶段-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与正读不…...
C语言太简单?这14道C语言谜题,你能答对几个
14个C语言的迷题以及答案,代码应该是足够清楚的,而且有相当的一些例子可能是我们日常工作可能会见得到的。通过这些迷题,希望你能更了解C语言。 如果你不看答案,不知道是否有把握回答各个谜题?让我们来试试。 下面的…...
Benchmark测试——fio——源码分析
1. main 1.1 parse_options() 解析选项,更新数据结构 1.1.1 fio_init_options() 1.1.2 fio_test_cconv(&def_thread.o) <cconv.c> 1.1.2.1 convert_thread_options_to_cpu() 传递options给数据结构 1.1.3 parse_cmd_line() switch语句多路选择&am…...
测量 R 代码运行时间的 5 种方法
简介 平常在撰写论文时,会需要比较算法之间的计算时间。本篇文章给出几种测量 R 代码运行时间的方法。本文是小编学习过程中的笔记,主要参考博客1,2。 1. 使用 Sys.time() 小编通常使用 Sys.time() 函数来计算时间。首先记录当前运行时刻&…...
Qt 第9课、计算器中缀转后缀算法
计算器核心算法: 1、将中缀表达式进行数字和运算符的分离 2、将中缀表达式转换成后缀表达式 3、通过后缀表达式计算最后的结果 二、计算器中缀转后缀算法 计算器中缀转后缀算法的意义在于把中缀表达式转换成后缀表达式,能够更好地计算 算法的基本思路…...
docker的使用方法
docker技术 同一个操作系统内跑多套不同版本依赖的业务 docker可以使同一个物理机中进程空间,网络空间,文件系统空间相互隔绝 虚拟机弊端:每个需要安装操作系统,太重量级,资源需要提前分配好 部署程序 开发环境 win…...
Kafka(五)生产者向发送消息的执行流程
(1)生产者要往 Kafka 发送消息时,需要创建 ProducerRecoder,代码如下: ProducerRecord<String,String> record new ProducerRecoder<>("CostomerCountry","Precision Products","France&q…...
华为OD机试模拟题 用 C++ 实现 - 简易压缩算法(2023.Q1)
最近更新的博客 【华为OD机试模拟题】用 C++ 实现 - 最多获得的短信条数(2023.Q1)) 文章目录 最近更新的博客使用说明简易压缩算法题目输入输出示例一输入输出说明示例二输入输出说明示例三输入输出说明...
MATLAB R2022b 安装教程
MATLAB R2022b 安装教程MathWorks 于2022年9月发布了 MATLAB 和 Simulink 产品系列的最新版本 Matlab R2022b版本 ,加入两个新产品: Medical Imaging Toolbox — 可视化、配准、分割和标注二维及三维医学图像Simscape Battery — 设计和仿真电池和储能系…...
PCI子系统
很多网络接口卡都是外围组件互联(Peripheral Compaonent Interconnect)设备,必须与Linux PCI子系统协同工作,并非所有的网络接口都是PCI设备,很多嵌入式设备的网络接口连接的就不是PCI总线,这些设备的初始化…...
Spring源码之IoC容器的Bean创建和依赖注入,DefaultListableBeanFactory容器为例
接上篇Spring源码之IoC容器初始化过程,以FileSystemXmlApplicationContext容器为例 因为FileSystemXmlApplicationContext使用的容器为DefaultListableBeanFactory,所以该篇基于DefaultListableBeanFactory的实现分析依赖注入过程。 目录获取Bean的总体流…...
网站后台怎么做alt标签/网站统计工具有哪些
现在的爬虫越来越难了,不再和之前的那样,随便抓个包就可以找到相关的 url ,然后 post 一下或者 get 一下数据就出来了。还有一个可能就是可能你以前用来学习的爬虫网站太简单了,还没有看见过那些猛的。上两周我就想弄弄知乎登陆&a…...
阿里巴巴网站域名建设/深圳网络推广
1. 需要使用svnant,从SVN中获取源码 需要使用的扩展包:svnant-1.3.1.zip里所有的jar 下载地址:http://subclipse.tigris.org/files/documents/906/49042/svnant-1.3.1.zip build.xml中的写法 <!--定义SVN地址--><property name"…...
上海网络平台网站建设/南宁seo计费管理
LiipThemeBundle LiipThemeBundle可以让您为您的每个Bundle添加主题。该主题一般位于您的Bundle目录的Resources/themes/<主题名>或正常的 Resources/views(如果没有找到的话)文件夹中。安装 步骤1:下载 LiipThemeBundle 进入Symfony2.…...
网站图片展示源代码/网络营销公司怎么注册
双链表比普通的链表多了指向前方数据的指针,方便对链表的查找。不过在实现方面却复杂了不少,增加或者删除数据的时候要考虑到前后数据指针,其中的操作顺序一定不能错。 #include<stdio.h> #include<stdlib.h> #define N 100 ty…...
html5网站建设方案/百度竞价推广怎么做
<script type"text/javascript">//正常版 // (function(){ // alert(好)//返回加 // })()(function(){alert(好好)}()); //正常版不能同时出现(如果一起出现了下面也无法执行了,二者出现一个就可正常运行)//特殊版 fu…...
路由器设置手机网站打不开/营销推广与策划
《基于单片机的交通灯控制系统的课程设计.doc》由会员分享,可免费在线阅读全文,更多与《基于单片机的交通灯控制系统的课程设计(最终版)》相关文档资源请在帮帮文库(www.woc88.com)数亿文档库存里搜索。1、,振荡器和电容应尽可能安装得与单片…...