[Spring] MyBatis操作数据库(进阶)
🌸个人主页:https://blog.csdn.net/2301_80050796?spm=1000.2115.3001.5343
🏵️热门专栏:
🧊 Java基本语法(97平均质量分)https://blog.csdn.net/2301_80050796/category_12615970.html?spm=1001.2014.3001.5482
🍕 Collection与数据结构 (92平均质量分)https://blog.csdn.net/2301_80050796/category_12621348.html?spm=1001.2014.3001.5482
🧀线程与网络(96平均质量分) https://blog.csdn.net/2301_80050796/category_12643370.html?spm=1001.2014.3001.5482
🍭MySql数据库(93平均质量分)https://blog.csdn.net/2301_80050796/category_12629890.html?spm=1001.2014.3001.5482
🍬算法(97平均质量分)https://blog.csdn.net/2301_80050796/category_12676091.html?spm=1001.2014.3001.5482
🍃 Spring(97平均质量分)https://blog.csdn.net/2301_80050796/category_12724152.html?spm=1001.2014.3001.5482
感谢点赞与关注~~~
目录
- 1. 数据库连接池
- 1.1 为什么会有连接池
- 1.2 常用的数据库连接池
- 2. 动态SQL
- 2.1 ``<if>``标签
- 2.2 ``<trim>``标签
- 2.3 ``<where>``标签
- 2.4 ``<set>``标签
- 2.5 ``<for each>``标签
- 2.6 ``<include>``标签
- 3. 案例练习(表白墙)
- 3.1 配置文件
- 3.2 Mapper层代码
- 3.3 Service层代码
- 3.4 Controller层代码
1. 数据库连接池
1.1 为什么会有连接池
数据库连接池技术也是一种池化技术,他与线程池类似,在通过Spring连接数据库的时候,避免了频繁的创建和销毁与数据库的连接.保证了资源的合理利用.
没有使用数据库连接池的情况: 在每一次在Spring中执行SQL语句的时候,都会先创建一个与数据库的连接对象,在执行完SQL语句之后,再关闭SQL语句,这种重复创建和销毁对象的行为比较浪费系统资源.
使用数据连接池的情况: 在程序启动的时候,会在连接池中创建Collection对象,在执行SQL语句的时候,会在连接池中申请一个连接对象,在执行SQL语句之后,又会把线程归还给连接池.
1.2 常用的数据库连接池
• C3P0
• DBCP
• Druid
• Hikari
目前比较流行的是Hikari,Druid,其中,Druid是阿里巴巴开源项目中的连接池.
其中Hikari是一个Spring程序中默认使用的连接池.如果想把连接池切换为Druid,我们需要在pom文件中引入依赖:
<dependency><groupId>com.alibaba</groupId><artifactId>druid-spring-boot-3-starter</artifactId><version>1.2.21</version>
</dependency>
2. 动态SQL
动态SQL可以完成不同场景下的SQL拼接.
2.1 <if>
标签
在我们注册用户的时候,我们有一个这样的问题,有时候有的选项不是必填项.在添加用户的时候SQL字段个数是不确定的.这时候就需要我们使用<if>
标签了.比如gender性别是非必填字段:
接口定义:
public Integer insertUser2(UserInfo userInfo);
sql:
<insert id="insertUser2">insert into userinfo (id,username,password,age,<if test="gender != null">gender,</if>phone) values (#{id},#{username},#{password},#{age},<if test="gender != null">#{gender},</if>#{phone})
</insert>
或者我们也可以使用注解的方式,使用<script></script>
标签把上面的xml语句括起来即可.但是我们不推荐用这种做法.
@Insert("<script>" +"INSERT INTO userinfo (username,`password`,age," +"<if test='gender!=null'>gender,</if>" +"phone)" +"VALUES(#{username},#{age}," +"<if test='gender!=null'>#{gender},</if>" +"#{phone})"+"</script>")
public Integer insertUser2(UserInfo userInfo);
注意if中的gender是对象的属性,不是SQL的字段,因为对象是从前端传过来的,我们在判断的时候,是判断前端有没有传值过来,而前段的值就是传到后端的方法参数中的.
2.2 <trim>
标签
上面只使用if标签有一定的问题.要是我们在拼接SQL语句的时候,if标签在最后一个字段,比如:
<insert id="insertUser2">insert into userinfo (id,username,password,age,gender,<if test="phone != null">phone</if>) values (#{id},#{username},#{password},#{age},#{gender},<if test="phone != null">#{phone}</if>)
</insert>
当我们没有phone属性的时候,我们在gender字段后面就会多上一个逗号,这显然不符合sql的语法,所以我们就需要使用<trim>
标签.
标签中有如下属性:
• prefix:表示整个语句块,以prefix的值作为前缀
• suffix:表示整个语句块,以suffix的值作为后缀
• prefixOverrides:表示整个语句块要去除掉的前缀
• suffixOverrides:表示整个语句块要去除掉的后缀
调整上面的插入语句:
<insert id="insertUser3">insert into userinfo<trim prefix="(" suffix=")" suffixOverrides="," prefixOverrides=",">id,username,password,age,gender,<if test="phone != null">phone</if></trim>values<trim prefix="(" prefixOverrides="," suffix=")" suffixOverrides=",">#{id},#{username},#{password},#{age},#{gender},<if test="phone != null">#{phone}</if></trim>
</insert>
假如所有的字段都是可选字段:
<insert id="insertUser4">insert into userinfo<trim prefixOverrides="," suffixOverrides="," suffix=")" prefix="("><if test="id != null">id,</if><if test="username != null">username,</if><if test="password != null">password,</if><if test="age != null">age,</if><if test="phone != null">phone</if></trim>values<trim prefix="(" suffix=")" suffixOverrides="," prefixOverrides=","><if test="id != null">#{id},</if><if test="username != null">#{username},</if><if test="password != null">#{password},</if><if test="age != null">#{age},</if><if test="gender != null">#{gender},</if><if test="phone != null">#{phone}</if></trim>
</insert>
trim标签中的参数的用意就是:在前面和后面只要有逗号,就都会去掉,之后再在sql语句中的前后拼接上括号.
这个标签就是把<trim>
中的内容当做一个字符串,对这个字符串进行整体加减前后缀.
在注解中写的方法和上面的if标签是一样的,这里不再赘述.
2.3 <where>
标签
下面这个场景,系统会根据我们的筛选条件,动态组装where条件.
这样的场景该如何实现呢?下面我们来看例子.
传入的用户对象,根据属性做where条件查询,用户对象中属性不为null的,都为查询条件.
接口定义:
public List<UserInfo> selectUser1(UserInfo userInfo);
根据传过来的对象限制查询条件.
sql:
<select id="selectUser1" resultType="com.jrj.mybatis.UserInfo">select * from userinfo<where><if test="gender != null">#{gender},</if><if test="age != null">#{age},</if><if test="deleteFlag != null">#{deleteFlag}</if></where>
</select>
<where>
标签和<trim>
标签类似,where可以去除掉前后的and和or,如果where后面没有字段的话,就没有where语句了,where关键字不予保留.效果和<trim prefix="where" prefixOverrides="and">
相同,但是使用这个标签的时候,当没有限制条件的时候,where关键字就会保留下来.
2.4 <set>
标签
根据传入的用户对象属性来更新用户数据,可以使用标签来指定动态内容.
方法接口:
public Integer updateUser1(UserInfo userInfo);
sql:
<update id="updateUser1">update userinfo<set><if test="username != null">username = #{username},</if><if test="age != null">age = #{age},</if><if test="gender != null">gender = #{gender}</if></set> where id = #{id}
</update>
<set>
标签和上面的<where>
标签一样,会自动去除逗号,也会根据是否有更新字段来判断是否要添加set关键字.与<trim prefix="set" suffixOverrides=",">
效果一样,但是在没有传入跟新字段的时候,不会去掉set关键字.
2.5 <for each>
标签
对集合进行遍历的时候,可以用这个标签,一般与sql语句中的in配合使用.
对集合进行遍历时可以使用该标签。标签有如下属性:
• collection:绑定方法参数中的集合,如List,Set,Map或数组对象
• item:遍历时的每⼀个对象
• open:语句块开头的字符串
• close:语句块结束的字符串
• separator:每次遍历之间间隔的字符串
比如根据多个用户id删除用户数据.
接口:
public Integer updateDeleteFlag1(List<UserInfo> userList);
sql:
<update id="updateDeleteFlag1">update userinfo set delet_flagwhere id in<foreach collection="userList" item="id" open="(" close=")">#{id}</foreach>
</update>
这里我们在删除用户数据的时候,使用的是逻辑删除的方式:
删除方式一共有两种,一种是逻辑删除,一种是物理删除,物理删除就是使用Delete语句,在计算机的存储空间中彻底删除,想要回复只能通过日志回滚的方式进行恢复,非常麻烦.而逻辑删除就是把表中每个数据的必备字段,delete_flag标记为无效的数值,并没有从硬盘上真正删除掉,恢复的时候只需要把这个数值改成有效数值即可.我们在企业开发的时候,一般用的都是逻辑删除.
[补充] 其中的collection参数也可以用list1,list2来表示,和前面的方法形参与sql语句传参类似.
2.6 <include>
标签
这个标签通常与<sql>
标签配合使用,在xml文件中,有一些sql语句是赘余的,即sql语句中的赘余片段.
我们可以对重复的代码片段段进行抽取,将其通过 <sql>
标签封装到⼀个SQL片段.之后在每一个sql语句中使用<include>
标签进行引用即可.
<sql>
: 对可以重复引用的sql语句进行定义,在参数id中定义该sql片段的名字.<include>
: 通过属性refid,指定引用的sql片段.
<sql id="selectAllColumn">id,username,password,age,gender,phone,delete_flag,create_time,update_time
</sql><select id="selectAllUser2" resultType="com.jrj.mybatis.UserInfo">select<include refid="selectAllColumn"></include>from userinfo
</select>
3. 案例练习(表白墙)
前面我们写了表白墙,但是在服务器重启之后,就会清空之前的数据,数据无法永久保留,这时候就需要引入MyBatis了,我们需要把数据存储在数据库中.
3.1 配置文件
spring:application:name: vindicatewall# 数据库连接配置datasource:url: jdbc:mysql://127.0.0.1:3306/mybatis_test?characterEncoding=utf8&useSSL=falseusername: rootpassword: qwe123524driver-class-name: com.mysql.cj.jdbc.Drivermybatis:configuration: # 配置打印 MyBatis⽇志log-impl: org.apache.ibatis.logging.stdout.StdOutImplmap-underscore-to-camel-case: true #配置驼峰⾃动转换
需要配置的选项有这几个,第一个是数据库相关配置,包括数据库url,用户名,密码,MySQl驱动类.其次,需要配置MyBatis中的日志打印和驼峰自动转换.
3.2 Mapper层代码
@Mapper
public interface MessageMapper {@Insert("insert into message_info (`from`,`to`,`message`) values " +"(#{from},#{to},#{message})")public Integer updateMessage(Message message);@Select("select * from message_info")public List<Message> selectAllMessage();
}
3.3 Service层代码
@Service
public class MessageService {@Autowiredpublic MessageMapper messageMapper;public Integer updateMessage(Message message){return messageMapper.updateMessage(message);}public List<Message> selectAllMessage(){return messageMapper.selectAllMessage();}
}
3.4 Controller层代码
@RestController
@RequestMapping("/messagewall")
public class MessageController {@Autowiredpublic MessageService messageService;@RequestMapping("/publish")public Boolean updateMessage(Message message){if (StringUtils.hasLength(message.getFrom())&&StringUtils.hasLength(message.getTo())&&StringUtils.hasLength(message.getMessage())){messageService.updateMessage(message);return true;}return false;}@RequestMapping("/getlist")public List<Message> selectAllMessage(){return messageService.selectAllMessage();}
}
Postman测试后端代码:
数据库已更新:
相关文章:

[Spring] MyBatis操作数据库(进阶)
🌸个人主页:https://blog.csdn.net/2301_80050796?spm1000.2115.3001.5343 🏵️热门专栏: 🧊 Java基本语法(97平均质量分)https://blog.csdn.net/2301_80050796/category_12615970.html?spm1001.2014.3001.5482 🍕 Collection与…...

【Websim.ai】一句话让AI帮你生成一个网页
【Websim.ai】一句话让AI帮你生成一个网页 网站链接 websim.ai 简介 websim.ai接入了Claude Sonnet 3.5,GPT-4o等常用的LLM,只需要在websim.ai的官网指令栏中编写相关指令,有点类似大模型的Prompt,指令的好坏决定了网页生成的…...

云计算实训16——关于web,http协议,https协议,apache,nginx的学习与认知
一、web基本概念和常识 1.Web Web 服务是动态的、可交互的、跨平台的和图形化的为⽤户提供的⼀种在互联⽹上浏览信息的服务。 2.web服务器(web server) 也称HTTP服务器(HTTP server),主要有 Nginx、Apache、Tomcat 等。…...

2024年必备技能:小红书笔记评论自动采集,零基础也能学会的方法
摘要: 面对信息爆炸的2024年,小红书作为热门社交平台,其笔记评论成为市场洞察的金矿。本文将手把手教你,即便编程零基础,也能轻松学会利用Python自动化采集小红书笔记评论,解锁营销新策略,提升…...

【Gitlab】SSH配置和克隆仓库
生成SSH Key ssh-keygen -t rsa -b 4096 私钥文件: id_rsa 公钥文件:id_rsa.pub 复制生成的ssh公钥到此处 克隆仓库 git clone repo-address 需要进行推送和同步来更新本地和服务器的文件 推送更新内容 git push <remote><branch> 拉取更新内容 git pull &…...

[Day 35] 區塊鏈與人工智能的聯動應用:理論、技術與實踐
區塊鏈的分布式存儲技術 區塊鏈技術自2008年比特幣白皮書發表以來,已經成為一種革命性的技術,帶來了許多創新。區塊鏈本質上是一個去中心化的分布式賬本,每個節點都持有賬本的副本,並參與記錄和驗證交易。分布式存儲是區塊鏈的重…...

Vue 3 中使用 inMap.js 实现蜂窝热力图的可视化
本文由ScriptEcho平台提供技术支持 项目地址:传送门 Vue 3 中使用 inMap.js 实现蜂窝热力图的可视化 应用场景介绍 蜂窝热力图是一种可视化技术,用于在地图上显示数据的分布情况。它将数据点划分为六边形单元格,并根据单元格内数据的密度…...

nginx隐藏server及版本号
1、背景 为了提高nginx服务器的安全性,降低被攻击的风险,需要隐藏nginx的server和版本号。 2、隐藏nginx版本号 在 http {—}里加上 server_tokens off; 如: http {……省略sendfile on;tcp_nopush on;keepalive_timeout 60;tcp_nodelay o…...

Oracle DBMS_XPLAN包
DBMS_XPLAN 包的解释和关键点 DBMS_XPLAN 包是 Oracle 数据库中一个重要的工具,它允许数据库管理员和开发人员以各种方式显示 SQL 语句的执行计划,这对于 SQL 优化和性能诊断至关重要。以下是主要函数及其描述: 用于显示执行计划的主要函数…...

【ffmpeg命令入门】分离音视频流
文章目录 前言音视频交错存储概念为什么要进行音视频交错存储:为什么要分离音视频流: 去除音频去除视频 总结 前言 FFmpeg 是一款强大的多媒体处理工具,广泛应用于音视频的录制、转换和流媒体处理等领域。它支持几乎所有的音频和视频格式&am…...

小红书笔记评论采集全攻略:三种高效方法教你批量导出
摘要: 本文将深入探讨如何利用Python高效采集小红书平台上的笔记评论,通过三种实战策略,手把手教你实现批量数据导出。无论是市场分析、竞品监测还是用户反馈收集,这些技巧都将为你解锁新效率。 一、引言:小红书数据…...

实战:ZooKeeper 操作命令和集群部署
ZooKeeper 操作命令 ZooKeeper的操作命令主要用于对ZooKeeper服务中的节点进行创建、查看、修改和删除等操作。以下是一些常用的ZooKeeper操作命令及其说明: 一、启动与连接 启动ZooKeeper服务器: ./zkServer.sh start这个命令用于启动ZooKeeper服务器…...

linux运维一天一个shell命令之 top详解
概念: top 命令是 Unix 和类 Unix 操作系统(如 Linux、macOS)中一个常用的系统监控工具,它提供了一个动态的实时视图,显示系统的整体性能信息,如 CPU 使用率、内存使用情况、进程列表等。 基本用法 root…...

大模型微调:参数高效微调(PEFT)方法总结
PEFT (Parameter-Efficient Fine-Tuning) 参数高效微调是一种针对大模型微调的技术,旨在减少微调过程中需要调整的参数量,同时保持或提高模型的性能。 以LORA、Adapter Tuning 和 Prompt Tuning 为主的PEFT方法总结如下 LORA 论文题目:LORA:…...

Spark+实例解读
第一部分 Spark入门 学习教程:Spark 教程 | Spark 教程 Spark 集成了许多大数据工具,例如 Spark 可以处理任何 Hadoop 数据源,也能在 Hadoop 集群上执行。大数据业内有个共识认为,Spark 只是Hadoop MapReduce 的扩展(…...

WPF多语言国际化,中英文切换
通过切换资源文件的形式实现中英文一键切换 在项目中新建Language文件夹,添加资源字典(xaml文件),中文英文各一个。 在资源字典中写上想中英文切换的字符串,需要注意,必须指定key值,并且中英文…...

Halcon深度学习分类模型
1.Halcon20之后深度学习支持CPU训练模型,没有money买显卡的小伙伴有福了。但是缺点也很明显,就是训练速度超级慢,推理效果也没有GPU好,不过学习用足够。 2.分类模型是Halcon深度学习最简单的模型,可以用在物品分类&…...

洗地机哪种牌子好?洗地机排行榜前十名公布
洗地机市场上品牌琳琅满目,每个品牌都有其独特的魅力和优势。消费者在选择时,往往会根据自己的实际需求、预算以及对产品性能的期望来做出决策。因此,无论是哪个品牌的洗地机,只要能够满足用户的清洁需求,提供便捷的操…...

C++中的虚函数与多态机制如何工作?
在C中,虚函数和多态机制是实现面向对象编程的重要概念。 虚函数是在基类中声明的函数,可以在派生类中进行重写。当基类的指针或引用指向派生类的对象时,通过调用虚函数可以实现动态绑定,即在运行时确定要调用的函数。 多态是指通…...

《LeetCode热题100》---<哈希三道>
本篇博客讲解 LeetCode热题100道中的哈希篇中的三道题。分别是 1.第一道:两数之和(简单) 2.第二道:字母异位词分组(中等) 3.第三道:最长连续序列(中等) 第一道࿱…...

秒懂C++之string类(下)
目录 一.接口说明 1.1 erase 1.2 replace(最好别用) 1.3 find 1.4 substr 1.5 rfind 1.6 find_first_of 1.7 find_last_of 二.string类的模拟实现 2.1 构造 2.2 无参构造 2.3 析构 2.4.【】运算符 2.5 迭代器 2.6 打印 2.7 reserve扩容 …...

github简单地操作
1.调节字体大小 选择options 选择text 选择select 选择你需要的参数就可以了。 2.配置用户名和邮箱 桌面右键,选择git Bash Here git config --global user.name 用户名 git config --global user.email 邮箱名 3.用git实现代码管理的过程 下载别人的项目 git …...

模型改进-损失函数合集
模版 第一步在哪些地方做出修改: 228行 self.use_wiseiouTrue 230行 self.wiou_loss WiseIouLoss(ltypeMPDIoU, monotonousFalse, inner_iouTrue, focaler_iouFalse) 238行 wiou self.wiou_loss(pred_bboxes[fg_mask], target_bboxes[fg_mask], ret_iouFalse…...

C++模板(初阶)
1.引入 在之前的笔记中有提到:函数重载(特别是交换函数(Swap)的实现) void Swap(int& left, int& right) {int temp left;left right;right temp; } void Swap(double& left, double& right) {do…...

下面关于Date类的描述错误的一项是?
下面关于Date类的描述错误的一项是? A. java.util.Date类下有三个子类:java.sql.Date、java.sql.Timestamp、java.sql.Time; B. 利用SimpleDateFormat类可以对java.util.Date类进行格式化显示; C. 直接输出Date类对象就可以取得日…...

【Python面试题收录】Python编程基础练习题①(数据类型+函数+文件操作)
本文所有代码打包在Gitee仓库中https://gitee.com/wx114/Python-Interview-Questions 一、数据类型 第一题(str) 请编写一个Python程序,完成以下任务: 去除字符串开头和结尾的空格。使用逗号(","&#…...

C# Nmodbus,EasyModbusTCP读写操作
Nmodbus读写 两个Button控件分别为 读取和写入 分别使用控件的点击方法 ①引用第三方《NModbus4》2.1.0版本 全局 public SerialPort port new SerialPort("COM2", 9600, Parity.None, 8, (StopBits)1); ModbusSerialMaster master; public Form1() port.Open();…...

spark常用参数调优
目录 1.set spark.grouping.sets.reference.hivetrue;2.set spark.locality.wait.rack0s3.set spark.locality.wait0s;4.set spark.executor.memoryOverhead 2G;5.set spark.sql.shuffle.partitions 1000;6.set spark.shuffle.file.buffer 256k7. set spark.reducer.maxSizeInF…...

C#/WinFrom TCP通信+ 网线插拔检测+客服端异常掉线检测
Winfor Tcp通信(服务端) 今天给大家讲一下C# 关于Tcp 通信部分,这一块的教程网上一大堆,不过关于掉网,异常断开连接的这部分到是到是没有多少说明,有方法 不过基本上最多的两种方式(1.设置一个超时时间,2.…...

一篇文章掌握Python爬虫的80%
转载:一篇文章掌握Python爬虫的80% Python爬虫 Python 爬虫技术在数据采集和信息获取中有着广泛的应用。本文将带你掌握Python爬虫的核心知识,帮助你迅速成为一名爬虫高手。以下内容将涵盖爬虫的基本概念、常用库、核心技术和实战案例。 一、Python 爬虫…...