博主主页: 码农派大星.
数据结构专栏:Java数据结构
数据库专栏:MySQL数据库
JavaEE专栏:JavaEE
软件测试专栏:软件测试
关注博主带你了解更多知识
目录
1. MyBatis概念
2. MyBatis⼊⻔
2.2 数据准备
2.3 配置数据库连接
2.4 完善持久层代码
2.5 测试
1.自己书写测试代码
2. 使⽤Idea⾃动⽣成测试
编辑
3. MyBatis的基础操作
3.1 打印⽇志
3.2 参数传递
未加@Param
加@Param
查多个参数:
编辑 总结: 编辑
3.3 增(Insert)
如果设置了@Param属性,#{...}需要使⽤参数.属性来获取
自增Id
3.4 删(Delete)
3.5 改(Update)
编辑 3.6 查(Select)
1 起别名
2 结果映射
3 配置驼峰⾃动转换
编辑
4. MyBatis XML配置⽂件
4.1 配置数据库连接字符串和MyBatis
4.2 写持久层代码
1 添加mapper接⼝
2 添加UserInfoXMLMapper.xml
3 单元测试
4.3 查(Select)
4.4 增
4.5 改
4.6 删
5 多表查询
6. #{} 和 ${}
6.1 #{} 和${}区别
7. 排序功能
8. like查询
9. 数据库连接池
使用
1. MyBatis概念
MyBatis是⼀款优秀的持久层框架,⽤于简化JDBC的开发
持久层:指的就是持久化操作的层,通常指数据访问层(dao),是⽤来操作数据库的
MyBatis是更简单完成程序和数据库交互的框架,也就是更简单的操作和读取数据库⼯具
2. MyBatis⼊⻔
Mybatis操作数据库的步骤:
1. 准备⼯作(创建springboot⼯程、数据库表准备、实体类)
2. 引⼊Mybatis的相关依赖,配置Mybatis(数据库连接信息)
3. 编写SQL语句(注解/XML)
4. 测试
2.1 Navicat 安装
这里我们会用到操作数据库的工具, 比如说Navigate ,小编为大家找好了,也感谢贡献者酷酷的洛克
Navigate 破解版 在这: 文件文件大小:95.9 M|https://kkdaj.lanzouq.com/iCJfT04o3pkh
教程: Navicat Premium 16 永久破解激活 - 酷酷的洛克 - 博客园文件
2.2 数据准备
安装完 Navicat 打开连接数据库就行
创建⽤⼾表
创建对应的实体类UserInfo
2.3 配置数据库连接
Mybatis中要连接数据库,需要数据库相关参数配置
MySQL驱动类登录名密码数据库连接字符串
application.yml⽂件,配置内容如下:
spring:datasource:url: jdbc:mysql://127.0.0.1:3306/mybatis_test?characterEncoding=utf8&useSSL=falseusername: rootpassword: '123456'driver-class-name: com.mysql.cj.jdbc.Driver
2.4 完善持久层代码
在项⽬中,创建持久层接⼝UserInfoMapper
@Mapper
public interface UserInfoMapper {@Select("select * from user_info")List<UserInfo> queryUserInfos();
}
2.5 测试
1.自己书写测试代码
@RequestMapping("/user")
@RestController
public class UserController {@Autowiredprivate UserService userService;@RequestMapping("/queryUserInfos")public List<UserInfo> queryUserInfos(){return userService.queryUserInfos();}
}
@Service
public class UserService {@Autowiredprivate UserInfoMapper userInfoMapper;public List<UserInfo> queryUserInfos(){return userInfoMapper.queryUserInfos();}
}
测试结果: 成功查询出数据
2. 使⽤Idea⾃动⽣成测试
@SpringBootTest
class UserInfoMapperTest {@Autowiredprivate UserInfoMapper userInfoMapper;@Testvoid queryUserInfos() {userInfoMapper.queryUserInfos().forEach(System.out::println);}}
运行成功:
3. MyBatis的基础操作
3.1 打印⽇志
打印日志需要先配置文件
application.yml, 配置内容如下:
mybatis:configuration: # 配置打印 MyBatis 执行的 SQLlog-impl: org.apache.ibatis.logging.stdout.StdOutImpl
重启程序运行:
3.2 参数传递
如果mapper接⼝⽅法形参只有⼀个普通类型的参数,#{…}⾥⾯的属性名可以随便写,如:#{id}、# {value}。建议和参数名保持⼀致
可以通过 @Param ,设置参数的别名,如果使⽤ @Param 设置,#{...}⾥⾯的属性名必须和@Param 设置的⼀样
@Select("select * from user_info where id = #{id}")UserInfo queryUserInfo(Integer id);
@Select("select * from user_info where id = #{id}")UserInfo queryUserInfo(@Param("id") Integer id);
未加@Param
加@Param
测试:
@Testvoid queryUserInfo() {System.out.println(userInfoMapper.queryUserInfo(1));}
结果:
查多个参数:
@Select("select * from user_info where id = #{id} and username = #{username}")UserInfo queryUserInfoByIdAndName(Integer id, String username);
使用@Param重命名会报错
总结: 
3.3 增(Insert)
@Insert("insert into user_info (username, password,age,gender,phone) " +"values(#{username},#{password},#{age},#{gender},#{phone})")Integer insert(UserInfo userInfo);
@Testvoid insert() {UserInfo userInfo = new UserInfo();userInfo.setUsername("cxkun");userInfo.setPassword("cxkun");userInfo.setAge(33);userInfo.setGender(2);userInfo.setPhone("10086");Integer result = userInfoMapper.insert(userInfo);System.out.println("添加数据: "+ result);}
测试结果:
如果设置了@Param属性,#{...}需要使⽤参数.属性来获取
@Insert("insert into user_info (username, password,age,gender,phone) " +"values(#{userInfo.username},#{userInfo.password},#{userInfo.age},#{userInfo.gender},#{userInfo.phone})")Integer insert2(@Param("userInfo") UserInfo userInfo);
测试结果:
自增Id
如果想要拿到⾃增id,需要在Mapper接⼝的⽅法上添加⼀个Options的注解
@Options(useGeneratedKeys = true,keyProperty = "id")@Insert("insert into user_info (username, password,age,gender,phone) " +"values(#{username},#{password},#{age},#{gender},#{phone})")Integer insert(UserInfo userInfo);
3.4 删(Delete)
@Delete("delete from user_info where id = #{id}" )Integer delete(Integer id);
3.5 改(Update)
@Update("update user_info set password =#{password} where id = #{id}")Integer update(UserInfo userInfo);
3.6 查(Select)
1 起别名
@Select("select id,username,password,age,gender,phone," +"delete_flag as deleteFlag,create_time as createTime,update_time as updateTime from user_info" )List<UserInfo> queryUserInfos2();
2 结果映射
@Results({@Result(column = "delete_flag",property = "deleteflag"),@Result(column = "create_time",property = "createtime"),@Result(column = "update_time",property = "updatetime")})@Select("select * from user_info" )List<UserInfo> queryUserInfos3();
并且还可实现复用:
3 配置驼峰⾃动转换
4. MyBatis XML配置⽂件
Mybatis的开发有两种⽅式:
1. 注解 2. XML
使⽤Mybatis的注解⽅式,主要是来完成⼀些简单的增删改查功能.如果需要实现复杂的SQL功能,建 议使⽤XML来配置映射语句,也就是将SQL语句写在XML配置⽂件中
步骤:
4.1 配置数据库连接字符串和MyBatis
spring:datasource:url: jdbc:mysql://127.0.0.1:3306/mybatis_test?characterEncoding=utf8&useSSL=falseusername: rootpassword: '123456'driver-class-name: com.mysql.cj.jdbc.Driver
mybatis:mapper-locations: classpath:mapper/*.xml
4.2 写持久层代码
持久层代码分两部分 1. ⽅法定义Interface 2. ⽅法实现:XXX.xml
1 添加mapper接⼝
import com.mybatis.model.UserInfo;
import org.apache.ibatis.annotations.Mapper;import java.util.List;@Mapper
public interface UserInfoXmlMapper {List<UserInfo> queryUserInfos();
}
2 添加UserInfoXMLMapper.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.mybatis.mapper.UserInfoXmlMapper"><select id="queryUserInfos" resultType="com.mybatis.model.UserInfo">select * from user_info;</select>
</mapper>
检查好配置:
3 单元测试
@SpringBootTest
class UserInfoXmlMapperTest {@Autowiredprivate UserInfoXmlMapper userInfoXmlMapper;@Testvoid queryUserInfos() {userInfoXmlMapper.queryUserInfos().forEach(System.out::println);}
}
测试成功:
4.3 查(Select)
1. 起别名 2. 结果映射 3. 开启驼峰命名
起别名和驼峰转换方法与注释一样,不在多说,接下来说结果映射
<resultMap id="XMLBaseMap" type="com.mybatis.model.UserInfo"><id column="id" property="id"></id><result column="delete_flag" property="deleteFlag"></result><result column="create_time" property="createTime"></result><result column="update_time" property="updateTime"></result></resultMap><select id="queryUserInfos2" resultMap="XMLBaseMap">select * from user_info;</select>
测试:
@Testvoid queryUserInfos2() {userInfoXmlMapper.queryUserInfos2().forEach(System.out::println);}
测试成功:
4.4 增
UserInfoXmlMapper接⼝:
Integer insertUserInfo(UserInfo userInfo);
UserInfoMapper.xml实现:
<insert id="insertUserInfo">insert into user_info (username, password, age,gender, phone)values (#{username},#{password}, #{age},#{gender},#{phone})</insert>
UserInfoXmlMapperTest测试:
@Testvoid insertUserInfo() {UserInfo userInfo = new UserInfo();userInfo.setUsername("cxk");userInfo.setPassword("cxk");userInfo.setGender(1);userInfo.setAge(18);userInfo.setPhone("13124124334");userInfoXmlMapper.insertUserInfo(userInfo);}
测试成功:
刷新数据库有新增的信息:
4.5 改
UserInfoXmlMapper接⼝:
Integer updateUserInfo(UserInfo userInfo);
UserInfoMapper.xml实现:
<update id="updateUserInfo">update user_info set phone = #{phone} where id = #{id}</update>
UserInfoXmlMapperTest测试:
@Testvoid updateUserInfo() {UserInfo userInfo = new UserInfo();userInfo.setPhone("12344444444");userInfo.setId(13);userInfoXmlMapper.updateUserInfo(userInfo);}
测试成功:
4.6 删
UserInfoXmlMapper接⼝:
Integer deleteUserInfo(Integer id);
UserInfoMapper.xml实现:
<delete id="deleteUserInfo">delete from user_info where id = #{id}</delete>
UserInfoXmlMapperTest测试:
@Testvoid deleteUserInfo() {userInfoXmlMapper.deleteUserInfo(14);}
测试成功:
5 多表查询
使用两张表进⾏多表关联查询
⽂章表的uid,对应⽤⼾表的id
补充实体类:
public class ArticleInfo {private Integer id;private String title;private String content;private Integer uid;private String username;private Integer age;private Integer deleteFlag;private Date createTime;private Date updateTime;
}
根据uid查询作者的名称等相关信息
@Mapper
public interface ArticleInfoMapper {@Select("select ta.*, tb.username, tb.age from articleinfo ta" +" left join user_info tb on ta.uid=tb.id" +" where ta.id = #{articleId}")ArticleInfo queryArticleInfo(Integer articleId);
}
测试
@SpringBootTest
class ArticleInfoMapperTest {@Autowiredprivate ArticleInfoMapper articleInfoMapper;@Testvoid queryArticleInfo() {articleInfoMapper.queryArticleInfo(1);}
}
查询成功:
6. #{} 和 ${}
@Select("select * from user_info where username = #{username}")UserInfo queryUserInfoByName(String username);
@Select("select * from user_info where username = ${username}")UserInfo queryUserInfoByName(String username);
6.1 #{} 和${}区别
#{} 和${} 的区别就是预编译SQL和即时SQL的区别
当客⼾发送⼀条SQL语句给服务器后,它的流程应该为:先解析语法和语义,校验SQL语句是否正确再优化SQL语句,制定执⾏计划最后 执⾏并返回结果
$是即时SQL(参数直接拼接),#是预编译SQL(参数通过占位的方式)
${} 允许直接将变量的值替换到 SQL 语句中(参数直接拼接的方式)。这种方式可能会导致 SQL 注入攻击,因为它直接将变量值拼接到 SQL 语句中,没有进行任何处理
#{}
:用于安全地插入参数(参数通过站位的方式),MyBatis 会为这些参数创建预处理语句,从而防止 SQL 注入攻击。
预编译SQL,编译⼀次之后会将编译后的SQL语句缓存起来,后⾯再次执⾏这条语句时,不会再次编译 (只是输⼊的参数不同),省去了解析优化等过程,以此来提⾼效率
SQL注⼊:是通过操作输⼊的数据来修改事先定义好的SQL语句,以达到执⾏代码对服务器进⾏攻击的⽅法
7. 排序功能
使⽤ ${} 可以实现排序查询,⽽使⽤ #{} 就不能实现排序查询了,SQL语句中,排序规则是不需要加引号,所以此时的${} 也不加引号
使⽤ #{} 查询时,desc前后⾃动给加了引号,导致sql错误
#{} 会根据参数类型判断是否拼接引号,如果参数类型为String就会加引号
改为${} 再试:
//排序@Select("select * from user_info order by id ${order}")List<UserInfo> queryUserInfoByOrder(String order);
测试成功:
除此之外,还有表名作为参数时,也只能使⽤ ${}
8. like查询
like 使⽤#{}报错
${}可以正确查出来,但是${}存在SQL注⼊的问题,所以不能直接使⽤${},使⽤mysql的内置函数concat()来处理
@Select("select * from user_info where username like CONCAT('%',#{name},'%')")List<UserInfo> queryUserInfoByLike(String name);
测试成功:
9. 数据库连接池
数据库连接池技术,避免频繁的创建连接,销毁连接
数据库连接池负责分配、管理和释放数据库连接,它允许应⽤程序重复使⽤⼀个现有的数据库连接, ⽽不是再重新建⽴⼀个
没有使⽤数据库连接池的情况:每次执⾏SQL语句,要先创建⼀个新的连接对象,然后执⾏SQL语句,SQL 语句执⾏完,再关闭连接对象释放资源.这种重复的创建连接,销毁连接⽐较消耗资源
使⽤数据库连接池的情况:程序启动时,会在数据库连接池中创建⼀定数量的Connection对象,当客⼾ 请求数据库连接池,会从数据库连接池中获取Connection对象,然后执⾏SQL,SQL语句执⾏完,再把 Connection归还给连接池
优点: 1. 减少了⽹络开销 2. 资源重⽤ 3. 提升了系统的性能
使用
1. Hikari : SpringBoot默认使⽤的数据库连接池
2. Druid
把默认的数据库连接池切换为Druid数据库连接池,只需要引⼊相关依赖
<dependency><groupId>com.alibaba</groupId><artifactId>druid-spring-boot-starter</artifactId><version>1.1.17</version></dependency>