当前位置: 首页 > news >正文

[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测试后端代码:
在这里插入图片描述
在这里插入图片描述
数据库已更新:
在这里插入图片描述

http://www.lryc.cn/news/409812.html

相关文章:

  • 【Websim.ai】一句话让AI帮你生成一个网页
  • 云计算实训16——关于web,http协议,https协议,apache,nginx的学习与认知
  • 2024年必备技能:小红书笔记评论自动采集,零基础也能学会的方法
  • 【Gitlab】SSH配置和克隆仓库
  • [Day 35] 區塊鏈與人工智能的聯動應用:理論、技術與實踐
  • Vue 3 中使用 inMap.js 实现蜂窝热力图的可视化
  • nginx隐藏server及版本号
  • Oracle DBMS_XPLAN包
  • 【ffmpeg命令入门】分离音视频流
  • 小红书笔记评论采集全攻略:三种高效方法教你批量导出
  • 实战:ZooKeeper 操作命令和集群部署
  • linux运维一天一个shell命令之 top详解
  • 大模型微调:参数高效微调(PEFT)方法总结
  • Spark+实例解读
  • WPF多语言国际化,中英文切换
  • Halcon深度学习分类模型
  • 洗地机哪种牌子好?洗地机排行榜前十名公布
  • C++中的虚函数与多态机制如何工作?
  • 《LeetCode热题100》---<哈希三道>
  • 秒懂C++之string类(下)
  • github简单地操作
  • 模型改进-损失函数合集
  • C++模板(初阶)
  • 下面关于Date类的描述错误的一项是?
  • 【Python面试题收录】Python编程基础练习题①(数据类型+函数+文件操作)
  • C# Nmodbus,EasyModbusTCP读写操作
  • spark常用参数调优
  • C#/WinFrom TCP通信+ 网线插拔检测+客服端异常掉线检测
  • 一篇文章掌握Python爬虫的80%
  • 【用户会话信息在异步事件/线程池的传递】