【JavaEE】Spring Boot MyBatis详解(二)

一.解决数据库字段名和对象属性名冲突的问题.

  • 产生这个问题的本质原因就是Java 属性名和数据库字段的命名规范不同. 这个问题的本质就是查询数据库返回了字段,但是不知道和Java对象的哪个属性相对应

1.注解的解决方法

  • 注解的解决方式有三种:
    • 方式一:给数据库字段起别名.== 本质上就是通过给数据库字段起别名的方式,让数据库的字段能供和Java对象的属性的对应关系能够对应的上.==
    • 方式二:指定结果映射. 数据返回了,但是不知道和谁对应,这个方式就是用映射的方式来指定数据间的对应关系.
    • 方式三:自动驼峰转换.

1.1 给数据库字段起别名的具体实现.

  • mapper层代码实现:
@Select("select id,username,delete_flag as deleteFlag,create_time as createTime,update_time as updateTime from userInfo")
    List<UserInfo> selectUserInfo();
  • 生成对应的测试代码,运行结果:
    在这里插入图片描述

1.2 指定结果映射的具体实现.

  • mapper层代码实现:
	@Results(id = "resultMap", value = {
            @Result(column = "delete_flag", property = "deleteFlag"),
            @Result(column = "create_time", property = "createTime"),
            @Result(column = "update_time", property = "updateTime")
    })
    @Select("select * from userInfo")
    List<UserInfo> selectUserInfo2();
  • 生成对应的测试代码,运行结果:
    在这里插入图片描述

配置一次之后下一次就可以直接使用这个对应关系.

@ResultMap("resultMap")
    @Select("select * from userInfo")
    public List<UserInfo> getUserInfoAll();

此处的参数和指定结果映射中的id相对应.

1.3 自动驼峰转换的具体实现.(更推荐使用这种方式)

  • 在yml中配置如下信息:
mybatis:
  configuration:
    map-underscore-to-camel-case: true  #自动驼峰转换

2.XML配置文件的解决方法

  • XML配置文件的解决方式和注解的方式相同也是以上三种方式:
    • 方式一:给数据库字段起别名.(跟注解的方式一样这里就不做详细的叙述了)
    • 方式二:指定结果映射.
    • 方式三:自动驼峰转换. (跟注解的方式一样这里就不做详细的叙述了)

2.1指定结果映射的具体实现

  • mapper层代码实现.
List<UserInfo> selectAll2();
  • 对应的XML配置文件.
	<resultMap id="BaseMap" type="com.tuanzi.ssm.springmybatis.model.UserInfo">
        <id column="id" property="id"/>
        <result column="delete_flag" property = "deleteFlag"/>
        <result column = "create_time" property = "createTime"/>
        <result column = "update_time" property = "updateTime"/>
    </resultMap>
    <select id="selectAll2" resultMap="BaseMap">
        select * from userInfo
    </select>
  • 生成对应的测试代码,运行结果:
    在这里插入图片描述

二.#{}和${}的区别和联系.

1.#{}和${}的使用.

  • mapper层代码:
	@Select("select * from userinfo where id=#{id}")
    List<UserInfo> getUserInfoById(Integer id);
    
    @Select("select * from userinfo where id=${id}")
    List<UserInfo> getUserInfoById2(Integer id);   
  • #{}运行结果:
    在这里插入图片描述
    我们输入的参数并没有在后面拼接,id的值是使用 ? 进行占位. 这种SQL 我们称之为"预编译SQL", 预编译SQL的本质类似于买火车票的占位行为, 显示出来这个位置已经有人了,但具体是谁,这个人高矮胖瘦,是男是女,都不重要,那个位置已经被他预定了. 然后根据传的参数来确定这个参数的具体类型并赋值.
  • ${}运行结果:
    在这里插入图片描述

从${}的运行结果我们可以看出此时的传参变成了直接拼接字符串.并会不跟据传入参数的类型来进行灵活转化.

2.#{}和${}参数解析之间的区别

  • mapper层代码:
	@Select("select * from userinfo where username = #{userName}")
    List<UserInfo> getUserInfoByUsername(String userName);

    @Select("select * from userinfo where username = ${userName}")
    List<UserInfo> getUserInfoByUsername2(String userName);
  • #{}运行结果:
    在这里插入图片描述
    此时代码正常执行,正确执行的sql语句为: select * from userinfo where username = ‘admin’

  • ${}运行结果:

在这里插入图片描述
此时代码执行会报错, 报的是SQLSyntaxErrorException, 由上述的图片我们可以看出直接拼接的内容与正确的sql的差别, 缺少’'/“”

#{} 使用的是预编译SQL, 通过 ? 占位的方式, 提前对SQL进行编译, 然后把参数填充到SQL语句中. #{} 会根据参数类型, 自动拼接引号 ‘’ .${} 会直接进行字符替换, 一起对SQL进行编译. 如果参数为字符串, 需要加上引号 ‘’

3.#{} 和 ${}区别

1. #{}的性能更高

  • 绝大多数情况下, 某⼀条 SQL 语句可能会被反复调用执行, 或者每次执行的时候只有个别的值不同(比如 select 的 where 子句值不同, update 的 set 子句值不同,insert 的 values 值不同). 如果每次都需要经过上面的语法解析, SQL优化、SQL编译等,则效率就明显不行了.
  • 预编译SQL,编译一次之后会将编译后的SQL语句缓存起来,后面再次执行这条语句时,不会再次编译(只是输入的参数不同), 省去了解析优化等过程, 以此来提高效率

2.#{}更安全可以防止sql注入(最重要的区别)

  • SQL注入:是通过操作输入的数据来修改事先定义好的SQL语句,以达到执行代码对服务器进行攻击的方法。

由于没有对用户输入进行充分检查,而SQL又是拼接而成,在用户输入参数时在参数中添加⼀些SQL关键字,达到改变SQL运行结果的目的,也可以完成恶意攻击。

  • sql注入的代码: ' or 1='1
  • 举个例子:
@Test
void queryByName() {
	List<UserInfo> userInfos = userInfoMapper.queryByName("' or 1='1");
 	System.out.println(userInfos);
}

在这里插入图片描述

可以看出来, 查询的数据并不是自己想要的数据. 假设如果这是用户的登录,那么即使在不知道用户密码的情况下,也可以通过sql注入进行登录所以用于查询的字段,尽量使用 #{} 预查询的方式. SQL注入是⼀种非常常见的数据库攻击手段, SQL注入漏洞也是网络世界中最普遍的漏洞之一.

3.排序功能(${}可以实现而#{}不可以实现)

  • mapper层代码:
	@Select("select * from userInfo order by id #{order} ")
    List<UserInfo> selectUserInfoOrder(String order);

    //也存在sql注入的问题,解决方法,可以使用穷举的方式进行校验.
    //也可以定义两个接口直接写死
    @Select("select * from userInfo order by id ${order} ")
    List<UserInfo> selectUserInfoOrder2(String order);
  • #{}的运行结果:
    在这里插入图片描述
    运行结果会报错,报错的原因是因为SQL错误, 与正确的SQL相比,desc是不需要加’'的.
  • ${}的运行结果:
    在这里插入图片描述

4.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);

此时代码执行会报错,很明显多了一个’', 如果把#{}改成${}可以解决问题,但会出现SQL注入的风险,解决方法是使用concat函数来解决问题

@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注入:一些数据库连接池如Druid提供了防SQL注入的功能。
  • SpringBoot默认使用的是hikari数据库连接池
    在这里插入图片描述

  • 常见的数据库连接池

    • C3P0:是一个开源的数据库连接池,稳定性良好。
    • DBCP:Apache提供的数据库连接池,速度快但存在已知BUG。
    • Druid:阿里巴巴提供的数据库连接池,集成了多种优点,并提供强大的监控功能。
  • Druid的maven依赖:

		<dependency>
			<groupId>com.alibaba</groupId>
			<artifactId>druid-spring-boot-3-starter</artifactId>
			<version>1.2.21</version>
		</dependency>

此时的运行结果:
在这里插入图片描述

四.动态SQL

1.标签

  • 思考一种情况,当添加用户的时候,有些情况某些值是非必填的选项,如果某一项或某几项没有传的时候该如何根据输入的具体参数处理SQL. 这个处理过的SQl称为动态SQL.
  • 接口定义:
Integer insertUserByCondition(UserInfo userInfo);

Mapper.xml实现:

<insert id="insertUserByCondition">
 INSERT INTO userinfo (
 	username,
 	`password`,
 	age,
 <if test="gender != null">
 	gender,
 </if>
 	phone)
 VALUES (
 	#{username},
 	#{age},
 <if test="gender != null">
 	#{gender},
 </if>
 	#{phone})
</insert>

2.trim标签.

  • 标签的相关属性
    • prefix:表示整个语句块,以prefix的值作为前缀
    • suffix:表示整个语句块,以suffix的值作为后缀
    • prefixOverrides:表示整个语句块要去除掉的前缀
    • suffixOverrides:表示整个语句块要去除掉的后缀
<insert id="insertUserInfoByCondition">
        insert into userinfo
        <trim prefix="(" suffix=")" prefixOverrides=",">
            <if test="username!=null">
                username
            </if>
            <if test="password!=null">
                ,password
            </if>
            <if test="age!=null">
                ,age
            </if>
            <if test="gender!=null">
                ,gender
            </if>
        </trim>
        values
        <trim prefix="(" suffix=")" prefixOverrides=",">
            <if test="username!=null">
                username
            </if>
            <if test="password!=null">
                ,password
            </if>
            <if test="age!=null">
                ,age
            </if>
            <if test="gender != null">
                ,#{gender}
            </if>
        </trim>
</insert>
  • 在以上 sql 动态解析时,会将第一个部分做如下处理:
    • 基于 prefix 配置,开始部分加上 (
    • 基于 suffix 配置,结束部分加上 )
    • 多个组织的语句都以 , 结尾,在最后拼接好的字符串还会以 , 结尾,会基于
      suffixOverrides 配置去掉最后一个 ,注意 中的 username 是传入对象的属性

在这里插入图片描述
此时就可以根据传的值来动态调整SQL语句了.

3.where标签.

<select id="queryUserInfoByCondition" resultType="com.tuanzi.ssm.springmybatis.model.UserInfo">
        select * from userinfo
        <where>
            <if test="age!=null">
                age = #{age}
            </if>
            <if test="gender!=null">
                and gender = #{gender}
            </if>
            <if test="deleteFlag!=null">
                and delete_flag = #{deleteFlag}
            </if>
        </where>
    </select>

只会在子元素有内容的情况下才插入where子句,而且会自动去除子句开头的AND或OR 以上标签也可以使用 替换, 但是此种情况下, 当子元素都没有内容时, where关键字也会保留

4.标签

<update id="updateUserInfoByCondition">
        update userInfo
        <set>
            <if test="password!=null">
                password = #{password}
            </if>
            <if test="age!=null">
                ,age = #{age}
            </if>
            <if test="gender!=null">
                ,gender = #{gender}
            </if>
        </set>
        where
        id = #{id}
    </update>
  • :动态的在SQL语句中插入set关键字,并会删掉额外的逗号. (用于update语句中)以上标签也可以使用 替换。

5.标签

  • 对集合进行遍历时可以使用该标签。标签有如下属性:
    • collection:绑定⽅法参数中的集合,如 List,Set,Map或数组对象
    • item:遍历时的每⼀个对象
    • open:语句块开头的字符串
    • close:语句块结束的字符串
    • separator:每次遍历之间间隔的字符串
	<delete id="batchDeleteByIds">
        delete from userinfo where id in
        <foreach collection="ids" open="(" close=")" item="id" separator=",">
            #{id}
        </foreach>
    </delete>

6.标签

  • 在xml映射文件中配置的SQL,有时可能会存在很多重复的片段,此时就会存在很多冗余的代码
    在这里插入图片描述
  • 我们可以对重复的代码片段进行抽取,将其通过 标签封装到⼀个SQL片段,然后再通过 标签进行引用
  • sql标签定义可重用的SQL片段
  • include标签通过属性refid,指定包含的SQL片段
 	<sql id="selectAllUserInfo">
        select * from userInfo
    </sql>

    <select id="selectAll" resultType="com.tuanzi.ssm.springmybatis.model.UserInfo">
        <include refid="selectAllUserInfo"></include>
    </select>

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mfbz.cn/a/727618.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

QT-QPainter实现一个动态充电的电池

1、效果 2、核心代码 #ifndef WIDGET_H #define WIDGET_H#include <QWidget> #include <QTimer>

全网最全postman接口测试教程和项目实战~从入门到精通

Postman实现接口测试内容大纲一览&#xff1a; 一、什么是接口&#xff1f;为什么需要接口&#xff1f; 接口指的是实体或者软件提供给外界的一种服务。 因为接口能使我们的实体或者软件的内部数据能够被外部进行修改。从而使得内部和外部实现数据交互。所以需要接口。 比如&…

番外篇 | 基于改进YOLOv5的安全帽佩戴检测 | 重参数化结构RepVGG + 空间对象注意力机制RCS-OSA模块

前言:Hello大家好,我是小哥谈。RCS-YOLO是一种目标检测算法,它是基于YOLOv3算法的改进版本。通过查看RCS-YOLO的整体架构可知,其中包括RCS-OSA模块。RCS-OSA模块在模型中用于堆叠RCS模块,以确保特征的复用并加强不同层之间的信息流动。本文针对安全帽佩戴的检测就是基于RC…

[leetcode hot 150]第十五题,三数之和

题目&#xff1a; 给你一个整数数组 nums &#xff0c;判断是否存在三元组 [nums[i], nums[j], nums[k]] 满足 i ! j、i ! k 且 j ! k &#xff0c;同时还满足 nums[i] nums[j] nums[k] 0 。请 你返回所有和为 0 且不重复的三元组。 注意&#xff1a;答案中不可以包含重复…

RSA 加密算法的基础数论、基本原理与 Python 实现

Title: RSA 加密算法的基础数论、基本原理与 Python 实现 文章目录 前言I. 数学原理1. 整数环2. 单位元3. 欧拉定理 II. 算法原理1. 扩展欧几里得算法2. RSA 非对称加密算法 III. 算法实现1. 源代码2. 测试结果 总结参考文献 前言 1977 年美国 MIT 的三位数学家 Ronald L. Riv…

startActivity启动流程

从桌面点击应用图标开始到Activity创建并执行onCreate&#xff0c;activity的启动涉及到两个进程system_server(AMS所在进程)和Zygote(如果进程没有创建需要先创建) 下图是从点击图标开始执行startActivity&#xff0c;一直到ActivityTaskSupervisor&#xff0c;到ActivityTas…

QT自定义标题栏窗口其二:实现拖动及可拉伸效果 + 顶部全屏/侧边半屏

1、效果 2、核心代码 #include "widget.h" #include "ui_widget.h"Widget::Widget(QWidget *parent): QWidget(parent<

CesiumJS整合ThreeJS插件封装

最近做项目有一个三维需求使用CesiumJS比较难以实现&#xff0c;发现THREEJS中效果比较合适&#xff0c;于是准备将THREEJS整合到CesiumJS中 为实现效果所需我们找到官方Integrating Cesium with Three.js博客&#xff0c;于是根据该博客提供的思路去实现整合 文章目录 一、创…

MySQL快速安装(mysql8.0.30区别之前yum安装)

目录 一.初始化环境并解压 二.创建程序用户管理 三.修改mysql目录和配置文件的权限 四.修改配置文件 五.设置环境变量&#xff0c;申明/宣告mysql命令便于系统识别 六.初始化数据库 七.设置系统识别&#xff0c;进行操作 八.初始化数据库密码 九.用户并设置密码 十.赋…

FinalReference 如何使 GC 过程变得拖拖拉拉

本文基于 OpenJDK17 进行讨论&#xff0c;垃圾回收器为 ZGC。 提示&#xff1a; 为了方便大家索引&#xff0c;特将在上篇文章 《以 ZGC 为例&#xff0c;谈一谈 JVM 是如何实现 Reference 语义的》 中讨论的众多主题独立出来。 FinalReference 对于我们来说是一种比较陌生的 R…

Python - 各种计算器合集【附源码】

计算器合集 一&#xff1a;极简版计算器二&#xff1a;简易版计算器三&#xff1a;不简易的计算器四&#xff1a;还可以计算器 一&#xff1a;极简版计算器 运行效果&#xff1a; import tkinter as tk import tkinter.messagebox win tk.Tk() win.title("计算器")…

如何高效应用与精准选择温补晶振

温补晶振(TCXO)是一种重要的时序元件&#xff0c;因其高精度和高稳定性在通信、导航、测控等多个领域中扮演着关键角色。晶发电子接下来将为您详细阐述温补晶振的选用和使用方法&#xff0c;助您更好地理解和运用这一核心元件。 一、温补晶振的工作原理 温补晶振能够实现在广…

绿茶集团重启IPO:流量渐退、业绩波动,还能讲出好故事吗?

近日&#xff0c;绿茶集团有限公司(下称“绿茶集团”)向港交所递交上市申请&#xff0c;花旗、招银国际为其联席保荐人。 回望绿茶集团的上市之路&#xff0c;可谓有诸多坎坷。该公司于2021年3月首度向港交所发起冲击&#xff0c;但却将中文版招股书中的“流动负债总额”错写成…

1.4自然语言的分布式表示-word2vec实操

文章目录 0写在前面1数据准备2CBOW模型结构的实现3交叉熵损失函数的前向计算3.1关于cross_entropy_error的计算3.2关于softmax 0写在前面 代码都位于&#xff1a;nlp&#xff1b;其他相关内容详见专栏&#xff1a;深度学习自然语言处理基础_骑着蜗牛环游深度学习世界的博客-CS…

深度学习模型训练中 学习率参数 设置大小问题及设置合适值

&#x1f4aa; 专业从事且热爱图像处理&#xff0c;图像处理专栏更新如下&#x1f447;&#xff1a; &#x1f4dd;《图像去噪》 &#x1f4dd;《超分辨率重建》 &#x1f4dd;《语义分割》 &#x1f4dd;《风格迁移》 &#x1f4dd;《目标检测》 &#x1f4dd;《暗光增强》 &a…

Mybatis Plus 详解 IService、BaseMapper、自动填充、分页查询功能

结构直接看目录 前言 MyBatis-Plus 是一个 MyBatis 的增强工具&#xff0c;在 MyBatis 的基础上只做增强不做改变&#xff0c;为简化开发、提高效率而生。 愿景 我们的愿景是成为 MyBatis 最好的搭档&#xff0c;就像 魂斗罗 中的 1P、2P&#xff0c;基友搭配&#xff0c;效…

Linux系统ubuntu20.04 无人机PX4 开发环境搭建(失败率很低)

Linux系统ubuntu20.04 无人机PX4 开发环境搭建 PX4固件下载开发环境搭建MAVROS安装安装地面站QGC PX4固件下载 PX4的源码处于GitHub&#xff0c;因为众所周知的原因git clone经常失败&#xff0c;此处从Gitee获取PX4源码和依赖模块。 git clone https://gitee.com/voima/PX4-…

使用 Python 中的美丽汤进行网络数据解析的完整指南

Beautiful Soup 是一个广泛使用的 Python 库&#xff0c;在数据提取方面发挥着重要作用。它为解析 HTML 和 XML 文档提供了强大的工具&#xff0c;使从网页中轻松提取有价值的数据成为可能。该库简化了处理互联网上非结构化内容的复杂过程&#xff0c;使您可以将原始网页数据转…

【nginx】 nginx核心功能

【nginx】 nginx核心功能 1.nginx核心功能 1. 反向代理 2. 负载均衡 3. 动静分离 4. nginx的高可用2. 反向代理 正向代理: 该服务器代理的是客户端&#xff0c;对于服务器来说&#xff0c;不知道真实客户端的ip。比如: 翻墙软件。 访问国外的服务器---使用了翻墙软件----对…

2024年【R1快开门式压力容器操作】考试及R1快开门式压力容器操作考试内容

题库来源&#xff1a;安全生产模拟考试一点通公众号小程序 2024年R1快开门式压力容器操作考试为正在备考R1快开门式压力容器操作操作证的学员准备的理论考试专题&#xff0c;每个月更新的R1快开门式压力容器操作考试内容祝您顺利通过R1快开门式压力容器操作考试。 1、【多选题…