XMl基本操作
引言
使⽤Mybatis的注解⽅式,主要是来完成⼀些简单的增删改查功能. 如果需要实现复杂的SQL功能,建议使⽤XML来配置映射语句,也就是将SQL语句写在XML配置⽂件中.
之前,我们学习了,用注解的方式来实现MyBatis
接下来我们学习XML的⽅式
- 配置数据库连接字符串和MyBatis
- 写持久层代码
MyBatis XML配置⽂件
配置连接字符串和MyBatis
# 数据库连接配置
spring:datasource:url: jdbc:mysql://127.0.0.1:3306/mybatis_test?
characterEncoding=utf8&useSSL=falseusername: rootpassword: rootdriver-class-name: com.mysql.cj.jdbc.Driver
# 配置 mybatis xml 的⽂件路径,在 resources/mapper 创建所有表的 xml ⽂件//mapper是目录,自己设置
//文件名的后缀部分必须是Mapper.xml不能修改,前面可以添加内容
//这里的*代表通配符
mybatis.mapper-locations=classpath:/myBatis/*Mapper.xml
mybatis:mapper-locations: classpath:mapper/**Mapper.xml 写持久层代码
- ⽅法定义 Interface
- ⽅法实现: XXX.xml

添加 mapper 接⼝
import com.example.demo.model.UserInfo;
import org.apache.ibatis.annotations.Mapper;
import java.util.List;
@Mapper
public interface UserInfoXMlMapper {List<UserInfo> queryAllUser();
} 添加 UserInfoXMLMapper.xml
在resources目录下添加前面在配置文件里面写的xml路径

在xml文件里面添加如下内容:
其中,mapper标签里面的namespace属性里面填的是 mapper接口的路径
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.example.demo.mapper.UserMapper"></mapper> <?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.example.demo.mapper.UserInfoXMlMapper"><select id="queryAllUser" resultType="com.example.demo.model.UserInfo">select username,`password`, age, gender, phone from userinfo</select>
</mapper> 
单元测试
@SpringBootTest
class UserInfoMapperTest {@Autowiredprivate UserInfoMapper userInfoMapper;@Testvoid queryAllUser() {List<UserInfo> userInfoList = userInfoMapper.queryAllUser();System.out.println(userInfoList);}} 增删改查操作
增(Insert)
Integer insertUser(UserInfo userInfo); <insert id="insertUser">insert into userinfo (username, `password`, age, gender, phone) values (#
{username}, #{password}, #{age},#{gender},#{phone})
</insert> Integer insertUser(@Param("userinfo") UserInfo userInfo); <insert id="insertUser">insert into userinfo (username, `password`, age, gender, phone) values(#{userinfo.username},#{userinfo.password},#{userinfo.age},#
{userinfo.gender},#{userinfo.phone})
</insert> <insert id="insertUser" useGeneratedKeys="true" keyProperty="id">insert into userinfo (username, `password`, age, gender, phone) values(#{userinfo.username},#{userinfo.password},#{userinfo.age},#
{userinfo.gender},#{userinfo.phone})
</insert 删(Delete)
Integer deleteUser(Integer id); <delete id="deleteUser">delete from userinfo where id = #{id}
</delete> 改(Update)
Integer updateUser(UserInfo userInfo); <update id="updateUser">update userinfo set username=#{username} where id=#{id}
</update> 查(Select)
<select id="queryAllUser" resultType="com.example.demo.model.UserInfo">select id, username,`password`, age, gender, phone, delete_flag,
create_time, update_time from userinfo
</select>
- 起别名
- 结果映射
- 开启驼峰命名
<resultMap id="BaseMap" type="com.example.demo.model.UserInfo"><id column="id" property="id"></id><result column="delete_flag" property="deleteFlag"></result><result column="create_time" property="createTime"></result><result column="update_time" property="updateTime"></result>
</resultMap>
<select id="queryAllUser" resultMap="BaseMap">select id, username,`password`, age, gender, phone, delete_flag,
create_time, update_time from userinfo
</select> 
#{} 和 ${}
#{} 和${} 使⽤
@Select("select username, `password`, age, gender, phone from userinfo where
id= #{id} ")
UserInfo queryById(Integer id);
select username, `password`, age, gender, phone from userinfo where id= ? 我们输⼊的参数并没有在后⾯拼接,id的值是使⽤ ? 进⾏占位. 这种SQL 我们称之为"预编译SQL"
@Select("select username, `password`, age, gender, phone from userinfo where
id= ${id} ")
UserInfo queryById(Integer id);

@Select("select username, `pasword`, age, gender, phone from userinfo where
username= #{name} ")
UserInfo queryByName(String name);
@Select("select username, `password`, age, gender, phone from userinfo where
username= ${name} ")
UserInfo queryByName(String name);

@Select("select username, `password`, age, gender, phone from userinfo where
username= '${name}' ")
UserInfo queryByName(String name);
从上⾯两个例⼦可以看出:#{} 使⽤的是预编译SQL, 通过 ? 占位的⽅式, 提前对SQL进⾏编译, 然后把参数填充到SQL语句中.#{} 会根据参数类型, ⾃动拼接引号 '' .${} 会直接进⾏字符替换, ⼀起对SQL进⾏编译. 如果参数为字符串, 需要加上引号 '' .参数为数字类型时, 也可以加上, 查询结果不变, 但是可能会导致索引失效, 性能下降.
#{} 和 ${}区别
#{} 和 ${} 的区别就是预编译SQL和即时SQL 的区别.
简单回顾:当客⼾发送⼀条SQL语句给服务器后, ⼤致流程如下:
- 解析语法和语义, 校验SQL语句是否正确
- 优化SQL语句, 制定执⾏计划
- 执⾏并返回结果
⼀条 SQL如果⾛上述流程处理, 我们称之为 Immediate Statements(即时 SQL)
性能更⾼
@Select("select username, `password`, age, gender, phone from userinfo where
username= '${name}' ")
List<UserInfo> queryByName(String name);
@Test
void queryByName() {List<UserInfo> userInfos = userInfoMapper.queryByName("admin");System.out.println(userInfos);
}
@Test
void queryByName() {List<UserInfo> userInfos = userInfoMapper.queryByName("' or 1='1");System.out.println(userInfos);
}
SQL注⼊是⼀种⾮常常⻅的数据库攻击⼿段, SQL注⼊漏洞也是⽹络世界中最普遍的漏洞之⼀. 如果发⽣在⽤⼾登录的场景中, 密码输⼊为 ' or 1='1 , 就可能完成登录(不是⼀定会发⽣的场景, 需要看登录代码如何写)
排序功能
@Select("select id, username, age, gender, phone, delete_flag, create_time,
update_time " +"from userinfo order by id ${sort} ")
List<UserInfo> queryAllUserBySort(String sort); 注意: 此处 sort 参数为String类型, 但是SQL语句中, 排序规则是不需要加引号 '' 的, 所以此时的${sort} 也不加引号
@Select("select id, username, age, gender, phone, delete_flag, create_time,
update_time " +"from userinfo order by id #{sort} ")
List<UserInfo> queryAllUserBySort(String sort); 
#{} 会根据参数类型判断是否拼接引号 ''如果参数类型为String, 就会加上 引号.
like 查询
like 使⽤ #{} 报错
@Select("select id, username, age, gender, phone, delete_flag, create_time,
update_time " +"from userinfo where username like '%#{key}%' ")
List<UserInfo> queryAllUserByLike(String key); @Select("select id, username, age, gender, phone, delete_flag, create_time,
update_time " +"from userinfo where username like concat('%',#{key},'%')")
List<UserInfo> queryAllUserByLike(String key); 数据库连接池
- 没有使⽤数据库连接池的情况: 每次执⾏SQL语句, 要先创建⼀个新的连接对象, 然后执⾏SQL语句, SQ语句执⾏完, 再关闭连接对象释放资源. 这种重复的创建连接, 销毁连接⽐较消耗资源
- 使⽤数据库连接池的情况: 程序启动时, 会在数据库连接池中创建⼀定数量的Connection对象, 当客⼾ 请求数据库连接池, 会从数据库连接池中获取Connection对象, 然后执⾏SQL, SQL语句执⾏完, 再把 Connection归还给连接池
- 减少了⽹络开销
- 资源重⽤
- 提升了系统的性能
常⻅的数据库连接池:
- C3P0
- DBCP
- Druid
- Hikari
⽬前⽐较流⾏的是 Hikari, DruidHikari : SpringBoot默认使⽤的数据库连接池
相关文章:
XMl基本操作
引言 使⽤Mybatis的注解⽅式,主要是来完成⼀些简单的增删改查功能. 如果需要实现复杂的SQL功能,建议使⽤XML来配置映射语句,也就是将SQL语句写在XML配置⽂件中. 之前,我们学习了,用注解的方式来实现MyBatis 接下来我们…...
Linux——Shell脚本和Nginx反向代理服务器
1. Linux中的shell脚本【了解】 1.1 什么是shell Shell是一个用C语言编写的程序,它是用户使用Linux的桥梁 Shell 既是一种命令语言,有是一种程序设计语言 Shell是指一种应用程序,这个应用程序提供了一个界面,用户通过这个界面访问…...
pyspark使用 graphframes创建和查询图的方法
1、安装graphframes的步骤 1.1 查看 spark 和 scala版本 在终端输入: spark-shell --version 查看spark 和scala版本 1.2 在maven库中下载对应版本的graphframes https://mvnrepository.com/artifact/graphframes/graphframes 我这里需要的是spark 2.4 scala 2.…...
【web】-flask-简单的计算题(不简单)
打开页面是这样的 初步思路,打开F12,查看头,都发现了这个表达式的base64加密字符串。编写脚本提交答案,发现不对; 无奈点开source发现源代码,是flask,初始化表达式,获取提交的表达式࿰…...
Apache Sqoop
Apache Sqoop是一个开源工具,用于在Apache Hadoop和关系型数据库(如MySQL、Oracle、PostgreSQL等)之间进行数据的批量传输。其主要功能包括: 1. 数据导入:从关系型数据库(如MySQL、Oracle等)中将…...
【Python】TensorFlow介绍与实战
TensorFlow介绍与使用 1. 前言 在人工智能领域的快速发展中,深度学习框架的选择至关重要。TensorFlow 以其灵活性和强大的社区支持,成为了许多研究者和开发者的首选。本文将进一步扩展对 TensorFlow 的介绍,包括其优势、应用场景以及在最新…...
第100+16步 ChatGPT学习:R实现Xgboost分类
基于R 4.2.2版本演示 一、写在前面 有不少大佬问做机器学习分类能不能用R语言,不想学Python咯。 答曰:可!用GPT或者Kimi转一下就得了呗。 加上最近也没啥内容写了,就帮各位搬运一下吧。 二、R代码实现Xgboost分类 (…...
【操作系统】定时器(Timer)的实现
这里写目录标题 定时器一、定时器是什么二、标准库中的定时器三、实现定时器 定时器 一、定时器是什么 定时器也是软件开发中的⼀个重要组件.类似于⼀个"闹钟".达到⼀个设定的时间之后,就执行某个指定 好的代码. 定时器是⼀种实际开发中⾮常常用的组件. ⽐如⽹络通…...
鸿蒙Navigation路由能力汇总
基本使用步骤: 1、新增配置文件router_map: 2、在moudle.json5中添加刚才新增的router_map配置: 3、使用方法: 属性汇总: https://developer.huawei.com/consumer/cn/doc/harmonyos-references/ts-basic-compone…...
1:1公有云能力整体输出,腾讯云“七剑”下云端
【全球云观察 | 科技热点关注】 曾几何时,云计算技术的兴起,为千行万业的数字化创新带来了诸多新机遇,同时也催生了新产业新业态新模式,激发出高质量发展的科技新动能。很显然,如今的云创新已成为高质量发…...
【iOS】APP仿写——网易云音乐
网易云音乐 启动页发现定时器控制轮播图UIButtonConfiguration 发现换头像 我的总结 启动页 这里我的启动页是使用Xcode自带的启动功能,将图片放置在LaunchScreen中即可。这里也可以通过定时器控制,来实现启动的效果 效果图: 这里放一篇大…...
react 快速入门思维导图
在掌握了react中一下的几个步骤和语法,基本上就可以熟练的使用react了。 1、组件的使用。react创建组件主要是类组件和函数式组件,类组件有生命周期,而函数式组件没有。 2、jsx语法。react主要使用jsx语法,需要使用babel和webpa…...
微软研究人员为电子表格应用开发了专用人工智能LLM
微软的 Copilot 生成式人工智能助手现已成为该公司许多软件应用程序的一部分。其中包括 Excel 电子表格应用程序,用户可以在其中输入文本提示来帮助处理某些选项。微软的一组研究人员一直在研究一种新的人工智能大型语言模型,这种模型是专门为 Excel、Go…...
[算法题]两个链表的第一个公共结点
题目链接: 两个链表的第一个公共结点 图示: 两个链表如果长度一致, 那么两人同时一人走一步, 如果存在公共结点, 迟早会相遇, 但是如果长度不一致单存在公共结点, 两人同时一人走一步不会相遇, 此时定义两个变量, node1 和 node2, 这两个变量分别从 x1 和 x2 开始走, 当其走完…...
MySQL事务管理(上)
目录 前言 CURD不加控制,会有什么问题? CURD满足什么属性,能解决上述问题? 事务 什么是事务? 为什么会出现事务 事务的版本支持 事务提交方式 查看事务提交方式 改变 MySQL 的自动提交模式: 事务常见操作方式 前…...
HTML2048小游戏
源代码在效果图后面 效果图 源代码 <!DOCTYPE html> <html lang"zh-CN"><head><meta charset"UTF-8"><meta name"viewport" content"widthdevice-width, initial-scale1.0"><title>2048 Game&l…...
为 android编译 luajit库、 交叉编译
时间:20200719 本机环境:iMac2017 macOS11.4 参考: 官方的文档:Use the NDK with other build systems 写在前边:交叉编译跟普通编译类似,无非是利用特殊的编译器、链接器生成动态或静态库; make 本质上是按照 Make…...
【音视频】音频重采样
文章目录 前言音频重采样的基本概念音频重采样的原因1. 设备兼容性2. 文件大小和带宽3. 音质优化4. 标准化和规范5. 多媒体同步6. 降低处理负载重采样的注意事项 总结 前言 音频重采样是指将音频文件的采样率转换成另一种采样率的过程。这在音频处理和传输中是一个常见且重要的…...
卷积神经网络学习问题总结
问题一: 深度学习中的损失函数和应用场景 回归任务: 均方误差函数(MSE)适用于回归任务,如预测房价、预测股票价格等。 import torch.nn as nn loss_fn nn.MSELoss() 分类任务: 交叉熵损失函数&…...
嵌入式面试总结
C语言中struct和union的区别 struct和union都是常见的复合结构。 结构体和联合体虽然都是由多个不同的数据类型成员组成的,但不同之处在于联合体中所有成员共用一块地址空间,即联合体只存放了一个被选中的成员,结构体中所有成员占用空间是累…...
接口测试中缓存处理策略
在接口测试中,缓存处理策略是一个关键环节,直接影响测试结果的准确性和可靠性。合理的缓存处理策略能够确保测试环境的一致性,避免因缓存数据导致的测试偏差。以下是接口测试中常见的缓存处理策略及其详细说明: 一、缓存处理的核…...
【杂谈】-递归进化:人工智能的自我改进与监管挑战
递归进化:人工智能的自我改进与监管挑战 文章目录 递归进化:人工智能的自我改进与监管挑战1、自我改进型人工智能的崛起2、人工智能如何挑战人类监管?3、确保人工智能受控的策略4、人类在人工智能发展中的角色5、平衡自主性与控制力6、总结与…...
React Native在HarmonyOS 5.0阅读类应用开发中的实践
一、技术选型背景 随着HarmonyOS 5.0对Web兼容层的增强,React Native作为跨平台框架可通过重新编译ArkTS组件实现85%以上的代码复用率。阅读类应用具有UI复杂度低、数据流清晰的特点。 二、核心实现方案 1. 环境配置 (1)使用React Native…...
P3 QT项目----记事本(3.8)
3.8 记事本项目总结 项目源码 1.main.cpp #include "widget.h" #include <QApplication> int main(int argc, char *argv[]) {QApplication a(argc, argv);Widget w;w.show();return a.exec(); } 2.widget.cpp #include "widget.h" #include &q…...
python执行测试用例,allure报乱码且未成功生成报告
allure执行测试用例时显示乱码:‘allure’ �����ڲ����ⲿ���Ҳ���ǿ�&am…...
Linux离线(zip方式)安装docker
目录 基础信息操作系统信息docker信息 安装实例安装步骤示例 遇到的问题问题1:修改默认工作路径启动失败问题2 找不到对应组 基础信息 操作系统信息 OS版本:CentOS 7 64位 内核版本:3.10.0 相关命令: uname -rcat /etc/os-rele…...
嵌入式学习笔记DAY33(网络编程——TCP)
一、网络架构 C/S (client/server 客户端/服务器):由客户端和服务器端两个部分组成。客户端通常是用户使用的应用程序,负责提供用户界面和交互逻辑 ,接收用户输入,向服务器发送请求,并展示服务…...
关于easyexcel动态下拉选问题处理
前些日子突然碰到一个问题,说是客户的导入文件模版想支持部分导入内容的下拉选,于是我就找了easyexcel官网寻找解决方案,并没有找到合适的方案,没办法只能自己动手并分享出来,针对Java生成Excel下拉菜单时因选项过多导…...
第八部分:阶段项目 6:构建 React 前端应用
现在,是时候将你学到的 React 基础知识付诸实践,构建一个简单的前端应用来模拟与后端 API 的交互了。在这个阶段,你可以先使用模拟数据,或者如果你的后端 API(阶段项目 5)已经搭建好,可以直接连…...
LangChain【6】之输出解析器:结构化LLM响应的关键工具
文章目录 一 LangChain输出解析器概述1.1 什么是输出解析器?1.2 主要功能与工作原理1.3 常用解析器类型 二 主要输出解析器类型2.1 Pydantic/Json输出解析器2.2 结构化输出解析器2.3 列表解析器2.4 日期解析器2.5 Json输出解析器2.6 xml输出解析器 三 高级使用技巧3…...

