Mybatis操作数据库
### 文章目录
- [Mybatis操作数据库](#{}和{}的区别 4.1 既然{}有SQL注入的风险,为什么还存在着这种方式呢 4.2 解决方式 五、模糊查询 六、数据库连接池)
- [@[toc]](#{}和{}的区别 4.1 既然{}有SQL注入的风险,为什么还存在着这种方式呢 4.2 解决方式 五、模糊查询 六、数据库连接池)
- [一、写在前面的规范](#{}和{}的区别 4.1 既然{}有SQL注入的风险,为什么还存在着这种方式呢 4.2 解决方式 五、模糊查询 六、数据库连接池)
- [二、普通SQL](#{}和{}的区别 4.1 既然{}有SQL注入的风险,为什么还存在着这种方式呢 4.2 解决方式 五、模糊查询 六、数据库连接池)
- [1. 注解形式](#{}和{}的区别 4.1 既然{}有SQL注入的风险,为什么还存在着这种方式呢 4.2 解决方式 五、模糊查询 六、数据库连接池)
- [1.1 注意事项](#{}和{}的区别 4.1 既然{}有SQL注入的风险,为什么还存在着这种方式呢 4.2 解决方式 五、模糊查询 六、数据库连接池)
- [1.2 如果数据库中的命名和Java中的命名不一致怎么映射?](#{}和{}的区别 4.1 既然{}有SQL注入的风险,为什么还存在着这种方式呢 4.2 解决方式 五、模糊查询 六、数据库连接池)
- [2. XML形式](#{}和{}的区别 4.1 既然{}有SQL注入的风险,为什么还存在着这种方式呢 4.2 解决方式 五、模糊查询 六、数据库连接池)
- [2.1 注意事项](#{}和{}的区别 4.1 既然{}有SQL注入的风险,为什么还存在着这种方式呢 4.2 解决方式 五、模糊查询 六、数据库连接池)
- [1.2 如果数据库中的命名和Java中的命名不一致怎么映射?](#{}和{}的区别 4.1 既然{}有SQL注入的风险,为什么还存在着这种方式呢 4.2 解决方式 五、模糊查询 六、数据库连接池)
- [三、动态SQL](#{}和{}的区别 4.1 既然{}有SQL注入的风险,为什么还存在着这种方式呢 4.2 解决方式 五、模糊查询 六、数据库连接池)
- [3.1 XML形式](#{}和{}的区别 4.1 既然{}有SQL注入的风险,为什么还存在着这种方式呢 4.2 解决方式 五、模糊查询 六、数据库连接池)
- [1. trim和if](#{}和{}的区别 4.1 既然{}有SQL注入的风险,为什么还存在着这种方式呢 4.2 解决方式 五、模糊查询 六、数据库连接池)
- [2. where](#{}和{}的区别 4.1 既然{}有SQL注入的风险,为什么还存在着这种方式呢 4.2 解决方式 五、模糊查询 六、数据库连接池)
- [3.set](#{}和{}的区别 4.1 既然{}有SQL注入的风险,为什么还存在着这种方式呢 4.2 解决方式 五、模糊查询 六、数据库连接池)
- [四、#{}和{}的区别](#{}和{}的区别 4.1 既然${}有SQL注入的风险,为什么还存在着这种方式呢 4.2 解决方式 五、模糊查询 六、数据库连接池)
- [4.1 既然{}有SQL注入的风险,为什么还存在着这种方式呢](#{}和{}的区别 4.1 既然${}有SQL注入的风险,为什么还存在着这种方式呢 4.2 解决方式 五、模糊查询 六、数据库连接池)
- [4.2 解决方式](#{}和{}的区别 4.1 既然{}有SQL注入的风险,为什么还存在着这种方式呢 4.2 解决方式 五、模糊查询 六、数据库连接池)
- [五、模糊查询](#{}和{}的区别 4.1 既然{}有SQL注入的风险,为什么还存在着这种方式呢 4.2 解决方式 五、模糊查询 六、数据库连接池)
- [六、数据库连接池](#{}和{}的区别 4.1 既然{}有SQL注入的风险,为什么还存在着这种方式呢 4.2 解决方式 五、模糊查询 六、数据库连接池)
一、写在前面的规范
-
数据库命名: 蛇形。如:user_name。
-
Java命名: 小驼峰。如:userName。
-
使用映射器(也即
@Mapper
)对于数据库和Java程序做链接🔗。
二、普通SQL
1. 注解形式
使用四个注解。
- @Select("")
- @Insert("")
- @Delete("")
- @Update("")
在括号中写的SQL语句和普通的没有区别。
java
@Select("select * from userinfo")
List<UserInfo> getUserInfoAll4();
// 获取自增ID
@Options(useGeneratedKeys = true, keyProperty = "id")
@Insert("insert into userinfo(userName,password,age,gender,phone) " +
"values (#{userName},#{password},#{age},#{gender},#{phone})")
Integer insertUserInfoByUser(UserInfo userInfo);
@Delete("delete from userinfo where userName = #{userName}")
Integer deleteUserInfoByName(String userName);
@Update("update userinfo set password = #{password}, age = #{age}, gender = #{gender} where id = #{id}")
Integer updateUserInfoByUser(UserInfo userInfo);
1.1 注意事项
- 接口中需要写上
@Mapper
注解
1.2 如果数据库中的命名和Java中的命名不一致怎么映射?
-
修改SQL语句,为数据库中的字段起别名
-
添加配置信息,使得驼峰命名和蛇形命名能够互相转换
javamap-underscore-to-camel-case: true #配置驼峰⾃动转换
-
编写映射关系,主要使用
@Result
和@Results
java// 3.映射关系 @Results({ @Result(column = "delete_flag", property = "deleteFlag"), @Result(column = "create_time", property = "createTime"), @Result(column = "update_time", property = "updateTime") }) @Select("select * from userinfo") List<UserInfo> getUserInfoAll3();
2. XML形式
使用4个标签。
<select>
<insert>
<delete>
<update>
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.example.springmybatis.mapper.UserInfoXMLMapper">
<insert id="insert">
insert into userinfo(username, password, age, gender, phone)
values (#{userName},#{password},#{age},#{gender},#{phone})
</insert>
<update id="update">
update userinfo set username=#{userName}, password=#{password}, age=#{age}, gender=#{gender}, phone=#{phone}
where id=#{id}
</update>
<delete id="delete">
delete from userinfo where id=#{id}
</delete>
<select id="selectAllUsers" resultType="com.example.springmybatis.model.UserInfo">
select * from userinfo
</select>
</mapper>
2.1 注意事项
- 标签是接口的实现,具体的接口定义和注解形式的一样
- 标签的xml文件中,
- 配置文件中的namespace需要和接口文件的全限定路径保持一致
- 标签(
<select id=''>
)中,id需要和方法名称保持一致
- 接口中需要写上
@Mapper
注解 - select语句需要写上
resultType
,因为select返回的可能是数字(影响行数),也可能是一个或多个对象(这时就需要写上对象的全限定路径)。
1.2 如果数据库中的命名和Java中的命名不一致怎么映射?
-
修改SQL语句,为数据库中的字段起别名
-
添加配置信息,使得驼峰命名和蛇形命名能够互相转换
javamap-underscore-to-camel-case: true #配置驼峰⾃动转换
-
编写映射关系
xml<resultMap id="BaseMap" type="com.example.springmybatis.model.UserInfo"> <id column="id" property="id"></id> <result column="username" property="userName"></result> <result column="password" property="password"></result> <result column="age" property="age"></result> <result column="gender" property="gender"></result> <result column="phone" property="phone"></result> <result column="delete_flag" property="deleteFlag"></result> <result column="create_time" property="createTime"></result> <result column="update_time" property="updateTime"></result> </resultMap> // resultMap使用自己定义的id <select id="selectAllUsers" resultType="com.example.springmybatis.model.UserInfo" resultMap="BaseMap"> select * from userinfo </select>
注意resultMap的id就相当于自定义的映射关系的名字,在select标签上需要写上使用的是哪个映射关系。
三、动态SQL
3.1 XML形式
1. trim和if
xml
<!-- 动态SQL-->
<insert id="insert2">
insert into userinfo
<trim prefix="(" suffix=")" suffixOverrides=",">
<if test="userName!=null">
username,
</if>
password, age, gender, phone
</trim>
values
<trim prefix="(" suffix=")" suffixOverrides=",">
<if test="userName!=null">
#{userName},
</if>
#{password},#{age},#{gender},#{phone}
</trim>
</insert>
- prefix是被包裹的代码段的前面需要去掉的符号
- suffixOverrides是被
<if>
包裹的代码段,需要后面去掉的符号- 这两个都有相对应的前(后)面的另一个属性
2. where
xml
<select id="selectAllUsers2" resultType="com.example.springmybatis.model.UserInfo">
select * from userinfo
<where>
<if test="userName!=null">
userName=#{userName}
</if>
<if test="age!=null">
and age=#{age}
</if>
<if test="id!=null">
and id=#{id}
</if>
</where>
</select>
- where可以给SQL加上where关键字
- 可以去掉没用到的and关键字
- 如果一个条件都没有,可以不生成where关键字
3.set
xml
<update id="update2">
update userinfo
<set>
<if test="userName!=null">
userName=#{userName},
</if>
<if test="age!=null">
age=#{age},
</if>
<if test="id!=null">
id=#{id},
</if>
</set>
where id=#{id}
</update>
- set可以去掉逗号
- 生成set关键字
四、#{}和${}的区别
- ${}是直接将字符串替换,存在SQL注入的风险
- #{}是将字符串加上单引号后,生成SQL语句
- ${}生成的是即时SQL,#{}生成的是预编译SQL(有?的占位符)
4.1 既然${}有SQL注入的风险,为什么还存在着这种方式呢
使用的场景是:SQL语句中不需要使用单引号就能完成,但是还是一个参数的情况。
- 排序,需要根据哪个字段进行排序
- 要查哪张表,根据表名进行SQL
比如:
sql
select * from userinfo order by age
这里的age就不需要添加引号。
但是存在SQL注入的风险,先将上一句话结束,然后写上drop database等,存在风险。
4.2 解决方式
-
可以加上参数判断
判断传进来的string是否是字段中的任意一个
-
或者直接封装成方法
方法名就叫:queryAllUsersByAge
五、模糊查询
因为存在两个"%",这两个%又不能由用户传入,所以需要使用${}。
虽然${}能够完成需求,但是有专门的拼接函数concat()
。
xml
<select id="queryAllUserByLike" resultType="com.example.springmybatis.model.UserInfo">
select * from userinfo where userName like concat('%',#{key},'%');
</select>
六、数据库连接池
需要更换直接在配置中更换。
像线程池一样,可以减少开销。可以使多个程序使用同一个已经连接上的数据库,而不是再去建立连接。
跟换阿里Durid数据库:
xml
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid-spring-boot-starter</artifactId>
<version>1.1.17</version>
</dependency>