Mybatis操作数据库
本节目标
目标
1.学习Mybatis的动态SQL查询
2.掌握在项目中的应用,可以使用SpringMVC 完成一些基础功能
文章目录
- 本节目标
- 前言
- 一、动态SQL是什么?
- 二、准备工作
- 1.配置相关信息
- 2.创建实体类,Mapper接口,XMl文件
- 三、标签
- 1.< if > 标签
- 2.< trim >标签
- 3.< where >标签
- 4< set >标签
- 5< foreach >标签
- 四.# 和$ 的区别
- ${}使用的场景
- 总结
前言
动态SQL
动态SQL是Mybatis强大特性之一,能够完成不同条件下的不同sql拼接,
可以参考官方文档:Mybatis动态sql
提示:以下是本篇文章正文内容,下面案例可供参考
一、动态SQL是什么?
动态SQL是MyBatis强大特性之一,如果你使用过JDBC或其他类似的框架,你应该能理解根据不同条件拼接SQL语句有多痛苦,例如,拼接时要确保不能忘记添加必要的空格,还要注意去掉列表最后一个列名的逗号,利用动态SQL,可以彻底摆脱这种痛苦
利用动态SQL并非是一件易事,但借助可用于任何SQL映射语句中强大的动态SQL语言,MyBatis显著的提升了这一特性的易用性
二、准备工作
1.配置相关信息
一.连接数据库
注意确认数据库名称,和密码
spring:
application:
name: mybatis
#数据库连接配置
datasource:
url: jdbc:mysql://127.0.0.1:3306/mybatis_test?characterEncoding=utf8&useSSL=false
username: root
password: liusan11
driver-class-name: com.mysql.cj.jdbc.Driver
二.配置MyBatis xml 的文件路径
保证路径与xml文件一致
mybatis:
mapper-locations: classpath:mapper/**Mapper.xml #配置Mybatis Xml的文件路径,在resource/mapper下创建所有表的xml文件
三.配置日志,驼峰命名(根据需求)
mybatis:
configuration:
log-impl: org.apache.ibatis.logging.stdout.StdOutImpl #打印日志
map-underscore-to-camel-case: true #配置驼峰自动转换
2.创建实体类,Mapper接口,XMl文件
回归主题,Mybatis的作用是管理数据的信息,如何通过后端进行读取数据,或对数据进行一些操作呢,并且采用动态SQL的方式 ,这不得不需要使用XML来完成接口的实验了
配置xml文件相关代码:
<?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.sponge.mapper.UserInfoXmlMapper">
#注意路径要和Mapper接口保持一致
</mapper>
创建实体类
@Data
public class UserInfo {
private Integer id;
private String username;
private String password;
private Integer age;
private Integer gender;
private String phone;
private Integer deleteFlag;
private Date createTime;
private Date updateTime;
}
数据库
所有工作准备完毕了!!!
三、标签
1.< if > 标签
代码如下(示例):
向数据库添加数据,通过字段名 username,password,gender,age进行添加
有时候这几个字段不是非必要字段,可不填
<insert id="insertUserInfo">
insert into user_info
<trim prefix="(" suffix=")" suffixOverrides=",">
<if test="username!=null">
username,
</if>
<if test="password!=null">
password,
</if>
<if test="gender!=null">
gender,
</if>
<if test="age!=null">
age,
</if>
</trim>
values
<trim prefix="(" suffix=")" suffixOverrides=",">
<if test="username!=null">
#{username},
</if>
<if test="password!=null">
#{password},
</if>
<if test="gender!=null">
#{gender},
</if>
<if test="age!=null">
#{age},
</if>
</trim>
</insert>
判断sql每个字段是否为空 ,为空就不传!
2.< trim >标签
如上述代码
此标签可用于去除多余的“ ,”,
属性
1.prefix : 加上 ”什么” 的前缀
2.suffix :加上“什么”的后缀
3.prefixOverrides:去掉“什么”的前缀
4.suffixOverrides:去掉“什么”的后缀
3.< where >标签
查询age = 18 并且 delete_flag = 0的数据
<select id="selectUserInfo" resultType="com.sponge.demo.model.UserInfo">
select * from user_info where
<if test="age!=null">
age = 14 and
</if>
<if test="deleteFlag!=null">
delete_flag = 0
</if>
</select>
使用if标签进行搭配 , 依然是判断字段是否有值而进行传递。
如上图Test方法 所示 , 查询结果是没问题的
现如果我们传 去一个空的userinfo ,而不对age 和deletFlag 赋值 ,则此时的sql语句为
select * from user_info where 导致多了一个 where 会出错,因此使用where标签可以判断后面字段名是否存在而选择性去掉where,可以防止出错
另外,如果仅给userinfo赋值一个age ,此时sql语句为 ==select * from user_info where age = 14 and == 导致多了一个and 会出错 此时可以加上trim标签 进行去除,同样可以使用where标签进行选择性管理 因此 where标签是一个不二的选择
终上所述,where标签的作用是 :选择性的去掉 where 和 and
即
<select id="selectUserInfo" resultType="com.sponge.demo.model.UserInfo">
select * from user_info
<where>
<if test="age!=null">
age = 14 and
</if>
<if test="deleteFlag!=null">
delete_flag = 0
</if>
</where>
</select>
4< set >标签
修改操作:通过id修改username ,password,gender
<update id="updateUserInfo">
update user_info
<set>
<if test="username!=null">
usernamm = #{username},
</if>
<if test="password!=null">
password = #{password},
</if>
<if test="gender!=null">
gender=#{gender}
</if>
where id = #{id}
</set>
</update>
同样的,如果 字段都为空,仅id 有值 ,那么sql语句就是update user_info set where id = ? 会导致多了一个
set 而出错 , 加上set 能解决吗?不能 , 因为这是更新语句 ,修改 , 就必须要使用set , 而set标签的作用在于可以去除 多余的“ ,”,这个问题也可以使用 trim 标签进行解决。
因此 set 标签的作用:仅 可以 去掉 多余的 “,” 相当于去掉了trim标签
5< foreach >标签
遍历,进行批量的操作,通过拼接的构成来构造sql
删除id 为 12,13 15 的数据
<delete id="deleteUserInfo">
delete from user_info where id in
<foreach collection="ids" separator="," close=")" open="(" item="id">
#{id}
</foreach>
</delete>
属性
1.collection : 参数集合名称
2.item:每一项的名称
3.separator:以什么分割
4.open: 以什么开始
5.close: 以什么结束
四.# 和$ 的区别
例1,通过ID查询用户信息
#{}
${}
例2 ,通过用户名(username)查询用户信息
#{}
${}
结果显示,使用${} 来传递 username(String)的字段 ,会出现SQl出错
原因是username是字符串类型,在进行判断时候 应该 写username = “admin” 需要加上双引号 , 而$ {} 是直接替换的 相当与直接把 admin 传上去就没有“”。
解决办法:手动加上‘’ 就可以变为字符串类型
根据上面不同的差异可以看出,
● #{} 是预编译SQL ,用"?"占位的方式提前对SQL进行编译 ,再把参数填充到SQL语句中,而且会根据参数类型,自动拼接引号‘’
● ${} 是即时SQL ,直接替换 ,不做任何处理
1.性能更高
绝大多数情况下,某一条SQl语句可能被反复调用执行,或者每次执行的时候只有个别的值不同(比如select的where子句值不同,upset的set子句值不同,insert的values的值不同,如果每次都需要上面的语法解析,SQL优化,SQL编译等,效率就明显不行了)
预编译SQL,编译一次后将编译后的SQL语句缓存起来,后面再次执行这条语句时,不会再次编译(只是输入的参数不同),省去了解析优化的过程来提高效率
2更安全,防止SQL注入
SQL注入:是通过操作输入的数据来修改实现定义好的SQL语句,以达到执行代码对服务器进行攻击的方法
由于没有对用户输入进行充分检查,而SQL又是拼接而成,在用户输入参数时,在参数添加一些SQL关键字,达到SQL运行结果的目的,
sql注入代码:‘ or 1 = '1就会导致数据库漏洞,查询的数据不是自己想要的数据,所以用于查询的字段,尽量使用#{}预查询的方式
${}使用的场景
1.排序功能
报错原因 使用#{sort } 表示 升序还是降序 ,但是报错 ,原因是# 会对已有的参数进行处理,若是字符串类型 会自动加上“” ,若是int 类型 不变
使用$后
因此 ${sort } 可以实现排序功能,而#{sort} 就不能实现排序功能
2.like查询
like使用#{}报错,而使用${} 存在SQL注入问题,因此使用mysql的内置函数 concat()处理
总结
以上就是我们动态Mysql的知识