


1.什么是MyBatis?
MyBatis是⼀款优秀的持久层框架,用于简化JDBC的开发 ,它可以帮助我们更方便、更快速的操作数据库。
持久层: 指的就是持久化操作的层, 通常指数据访问层(dao), 是用来操作数据库的。

工作流程


三要素


2.MyBatis入门

2.1 准备工作
(1)创建工程
创建springboot 工程,并导入mybatis 的起步依赖、mysql的驱动包。


手动添加Mybatis(后续在已有项目中添加可以用此方法)

(2)数据准备
创建用户表
sql
-- 创建数据库
DROP DATABASE IF EXISTS mybatis_test;
CREATE DATABASE mybatis_test DEFAULT CHARACTER SET utf8mb4;
-- 使用数据数据
USE mybatis_test;
-- 创建表[用户表]
DROP TABLE IF EXISTS user_info;
CREATE TABLE `user_info` (
`id` INT ( 11 ) NOT NULL AUTO_INCREMENT,
`username` VARCHAR ( 127 ) NOT NULL,
`password` VARCHAR ( 127 ) NOT NULL,
`age` TINYINT ( 4 ) NOT NULL,
`gender` TINYINT ( 4 ) DEFAULT '0' COMMENT '1-男 2-女 0-默认',
`phone` VARCHAR ( 15 ) DEFAULT NULL,
`delete_flag` TINYINT ( 4 ) DEFAULT 0 COMMENT '0-正常, 1-删除',
`create_time` DATETIME DEFAULT now(),
`update_time` DATETIME DEFAULT now() ON UPDATE now(),
PRIMARY KEY ( `id` )
) ENGINE = INNODB DEFAULT CHARSET = utf8mb4;
-- 添加用户信息
INSERT INTO mybatis_test.user_info( username, `password`, age, gender, phone )
VALUES ( 'admin', 'admin', 18, 1, '18612340001' );
INSERT INTO mybatis_test.user_info( username, `password`, age, gender, phone )
VALUES ( 'zhangsan', 'zhangsan', 18, 1, '18612340002' );
INSERT INTO mybatis_test.user_info( username, `password`, age, gender, phone )
VALUES ( 'lisi', 'lisi', 18, 1, '18612340003' );
INSERT INTO mybatis_test.user_info( username, `password`, age, gender, phone )
VALUES ( 'wangwu', 'wangwu', 18, 1, '18612340004' );
创建对应的实体类 UserInfo
实体类的属性名与表中的字段名⼀⼀对应
java
import lombok.Data;
import java.util.Date;
@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;
}

2.2 配置数据库连接字符串
Mybatis中要连接 数据库,需要数据库 相关参数配置:MySQL驱动类、登录名、密码、数据库连接字符串。
如果是application.yml 文件,配置内容如下: (复制粘贴即可)
java
# 数据库连接配置
spring:
datasource:
url: jdbc:mysql://127.0.0.1:3306/mybatis_test?characterEncoding=utf8&useSSL=false
username: root
password: root
driver-class-name: com.mysql.cj.jdbc.Driver


2.3 @Mapper @Select写持久层代码
在项目中,创建持久层接口 UserInfoMapper
写出SQL语句,通过MyBatis实现此语句
java
@Mapper
public interface UserInfoMapper {
@Select("SELECT * FROM `user_info`")
public List<UserInfo> selectList();
}

返回类型 :List<UserInfo> 返回一个 UserInfo 对象组成的列表 ,每个UserInfo 对象对应数据库中的一行数据.

2.4 单元测试
(1)方法1
先使用http请求调用方法看是否成功,先补全 controller 和 service层代码。


浏览器发起请求,先请求Controller ,Controller接收到请求之后,调用Service 进行业务逻辑处理,Service再调用Dao ,再从数据库中读取。


(2)方法2
在创建出来的SpringBoot工程中,在src下的test目录 下,已经自动 帮我们创建好了测试类 ,我们可以直接使用这个测试类来进行测试。
测试类上添加了注解**@SpringBootTest** ,该测试类在运行时,就会自动加载Spring的运行环境。
我们通过**@Autowired** 这个注解,注入我们要测试的类,就可以开始进行测试了。

java
@SpringBootTest
class MybatisDemoApplicationTests {
@Autowired
private UserInfoMapper userInfoMapper;
@Test
void contextLoads() {
List<UserInfo> userInfoList = userInfoMapper.selectList();
System.out.println(userInfoList);
}
}
也可以同时加几个方法,可以一次测试一个,也可以同时测试。

(3)方法3
使用Idea自动生成测试类

在执行测试方法前后 若有需要统一进行处理 的东西可以放在Before和After中,不需要可以不选。
书写测试代码,记得加**@SpringBootTest 注解**,加载Spring运行环境。

java
import com.example.mybatis.demo.model.UserInfo;
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import java.util.List;
import static org.junit.jupiter.api.Assertions.*;
@SpringBootTest
class UserInfoMapperTest {
@Autowired
private UserInfoMapper userInfoMapper;
@BeforeEach
void setUp() {
System.out.println("BeforeEach......");
}
@AfterEach
void tearDown() {
System.out.println("AfterEach......");
}
@Test
void selectList() {
List<UserInfo> userInfoList = userInfoMapper.selectList();
System.out.println(userInfoList);
}
}
也可以同时加几个方法,可以一次测试一个,也可以同时测试。
3.MyBatis的基础操作
3.1 打印日志

java
mybatis:
configuration: # 配置打印 MyBatis⽇志
log-impl: org.apache.ibatis.logging.stdout.StdOutImpl

重新运行程序,可以看到SQL执行内容、传递参数、执行结果。

3.2 查 @Select
我们在上面查询时发现,有几个字段是没有赋值 的,只有Java对象属性 和数据库字段一模一样 时,才会进行赋值。


输出null是因为名称不匹配
解决办法
(1)起别名
在SQL语句 中,给列名起别名 ,保持别名 和实体类属性名一样。
java
@Select("SELECT id, username, `password`, age, gender, phone, delete_flag AS deleteFlag, " +
"create_time AS createTime, update_time AS updateTime FROM `user_info`")
public List<UserInfo> selectList2();
SQL语句太长时,使用加号 + 进行字符串拼接。

测试一下

(2)结果映射@Results
@Results 注解--MyBatis 注解方式 中用于字段映射配置 的注解,它告诉 MyBatis 如何将数据库查询结果的列(column)映射到 Java 实体类的属性(property)。
@Results 注解包含一个或多个@Results 注解,每个 @Results注解对应一个字段的映射。
java
@Select("SELECT * FROM `user_info`")
@Results({
@Result(column = "delete_flag",property = "deleteFlag"),
@Result(column = "create_time",property = "createTime"),
@Result(column = "update_time",property = "updateTime")
})
List<UserInfo> selectList3();

测试一下


(3)开启驼峰命名(最推荐)
通常数据库列 使用蛇形命名法 进行命名(下划线 分割各个单词),而Java属性 ⼀般遵循驼峰命名法约定。
为了在这两种命名方式之间启用自动映射,需要将 mapUnderscoreToCamelCase 设置为 true。
java
mybatis:
configuration:
map-underscore-to-camel-case: true #配置驼峰⾃动转换

Java代码不 做任何处理,添加上述配置,运行代码。



注:为规避Windows(不区分大小写) 与 Linux(区分大小写) 之间的差异,数据库表名和字段名统一使用小写命名(确保在不同操作系统间的兼容性,避免因大小写不一致导致的查询错误)
3.3 参数传递 #{}
需求: 查找id=3 的用户,对应的SQL就是:select * from user_info where id=3
返回类型为 List<UserInfo> 是为了返回一个 UserInfo 对象组成的列表 ,每个UserInfo 对象对应数据库 中的一行数据,现在只有一行 数据,直接用UserInfo即可。
java
@Select("SELECT * FROM `user_info` WHERE id = 3")
UserInfo selectById();

测试一下

但是这样的话,只能 查找id=3的数据,所以SQL语句中的id值不能写成固定数值 ,需要变为动态的数值****。
解决方案:在 selectById 方法中添加一个参数(id),将方法中的参数,传给SQL语句 使用 #{}的方式获取方法中的参数。
java
@Select("SELECT * FROM `user_info` WHERE id = #{id}")
UserInfo selectById2(Integer id);

测试一下

再写一个俩参数 的,此时返回多个结果仍需要List。
java
@Select("SELECT * FROM `user_info` WHERE age = #{age} and gender = #{gender}")
List<UserInfo> selectByAgeAndGender(Integer age, Integer gender);

测试一下

注意:

3.4 增 @Insert
可以使用UserInfo对象来获取参数 ,返回类型为修改的行数。
java
@Insert("insert into user_info (username, `password`, age) " +
"VALUE(#{username}, #{password}, #{age})")
Integer insertUser(UserInfo userInfo);



刷新一下


返回主键


3.5 删 @Delete
java
@Delete("delete from user_info where id = #{id}")
Integer deleteUser(Integer id);


刷新一下

3.6 改 @Update
可以使用UserInfo对象来获取参数
java
@Update("update user_info set gender = #{gender}, delete_flag = #{deleteFlag} where id = #{id}")
Integer updateUser(UserInfo userInfo);

**@NoArgsConstructor 注解说明:**它会生成一个无参数的构造函数。

测试用例

刷新一下

4.MyBatis XML配置文件

关于开发中使用哪种模式这个问题,没有明确答案,自己随意,在公司跟内部用一样的。
4.1 配置连接字符串和MyBatis
此步骤需要进行两项 设置,数据库连接字符串 设置和 MyBatis 的 XML 文件配置。
如果是application.yml文件,配置内容如下:
java
# 数据库连接配置
spring:
datasource:
url: jdbc:mysql://127.0.0.1:3306/mybatis_test?characterEncoding=utf8&useSSL=false
username: root
password: root
driver-class-name: com.mysql.cj.jdbc.Driver
# 配置 mybatis xml 的⽂件路径,在 resources/mapper 创建所有表的 xml ⽂件
mybatis:
mapper-locations: classpath:mapper/**Mapper.xml
classpath就表示resources目录
路径可以修改 ,如把mapper改成mybatis ,自己在resources 中建一个mybatis包即可。


4.2 写持久层代码
持久层代码分两 部分:方法定义Interface、方法实现XXX.xml

(1)**方法定义:**添加mapper接口
数据持久层的接口定义:
java
import com.example.mybatis.demo.model.UserInfo;
import org.apache.ibatis.annotations.Mapper;
import java.util.List;
@Mapper
public interface UserInfoMapperXML {
List<UserInfo> selectList();
}

(2)**方法实现:**添加 UserInfoXMLMapper.xml
数据持久成的实现 ,MyBatis的固定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.example.demo.mapper.UserInfoMapper">
</mapper>
创建UserInfoXMLMapper.xml ,路径参考yml中的配置。

namespace表示要实现哪个接口, 根据自己的项目进行修改,可以按住类名 Ctrl+点击进去查看对不对。


安装一个插件 MybatisX ,可以方便生成一些代码。
或者也可以直接 Alt+Enter 快捷键生成



还需要自己补上XML 文件中缺少的SQL 语句
sql
select * from user_info


(3)单元测试

4.3 查(Select)
同样的,使用XML的方式进行查询,也存在数据封装 的问题;只有Java对象属性 和数据库字段一模一样 时,才会进行赋值。
解决办法和注解 类似:起别名、结果映射、开启驼峰命名
其中13的解决办法和注解一样,不再多说,接下来看下xml如果来写结果映射。



测试一下,可以先把配置文件中的驼峰配置自动转换代码删掉,测试完再加回去。

4.4 增(Insert)
与注解一样 ,可以使用UserInfo对象来获取参数 ,返回类型为修改的行数。
方法定义:
java
Integer insertUser(UserInfo userInfo);
方法实现:
XML
<insert id="insertUser">
insert into user_info (username, `password`, age)
VALUE(#{username}, #{password}, #{age})
</insert>


测试一下





4.5 删(Delete)
方法定义:
java
Integer deleteUserById(Integer id);
方法实现:
XML
<delete id="deleteUserById">
delete from user_info where id = #{id}
</delete>




4.6 改(Update)
方法定义:
java
Integer updateUser(UserInfo userInfo);
方法实现:
XML
<update id="updateUser">
update user_info set gender = #{gender}, delete_flag = #{deleteFlag} where id = #{id}
</update>




5.其他查询操作
5.1 多表查询
(1)数据准备
上面建了⼀张用户表 ,我们再来建一张文章表 ,进行多表关联查询。
文章表 的 uid 对应用户表 的id
sql
-- 创建文章表
DROP TABLE IF EXISTS article_info;
CREATE TABLE article_info (
id INT PRIMARY KEY auto_increment,
title VARCHAR ( 100 ) NOT NULL,
content TEXT NOT NULL,
uid INT NOT NULL,
delete_flag TINYINT ( 4 ) DEFAULT 0 COMMENT '0-正常, 1-删除',
create_time DATETIME DEFAULT now(),
update_time DATETIME DEFAULT now()
) DEFAULT charset 'utf8mb4';
-- 插入测试数据
INSERT INTO article_info ( title, content, uid ) VALUES ( 'Java', 'Java正文', 1 );
创建实体类

先试试文章表可不可用


(2)数据查询
需求:根据uid查询作者的名称等相关信息
SQL语句
sql
SELECT ta.*, tb.username, tb.age FROM `article_info` ta
left join user_info tb on ta.uid = tb.id
where ta.id = 1
接口定义:要注意sql语句的空格 ,还有**参数#{}**修改。
java
import com.example.mybatis.demo.model.ArticleInfo;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Select;
@Mapper
public interface ArticleInfoMapper {
@Select("SELECT ta.*, tb.username, tb.age FROM `article_info` ta " +
"left join user_info tb on ta.uid = tb.id " +
"where ta.id = #{id}")
ArticleInfo queryArticleInfo(Integer id);
}

补充实体类

测试用例


5.2 #{}预编译SQL、${}即时SQL(面试题)
(1)#{}和${}的使用
Interger 和 String类型的参数


使用Idea自动生成测试类 
观察打印的日志


(2)#{}和${}的区别
${}即时SQL--存在SQL注入的问题



5.3 排序功能




5.4 like查询




6.数据库连接池
6.1 介绍


6.2 使用

Hikari: SpringBoot 默认使用的数据库连接池。

Druid :阿里巴巴 开源的数据库连接池项目,功能强大,性能优秀,是Java语言最好的数据库连接池之一。
官方地址:https://github.com/alibaba/druid/tree/master/druid-spring-boot-starter
学习文档:https://github.com/alibaba/druid/wiki/%E9%A6%96%E9%A1%B5
如果我们想把默认的数据库连接池切换为Druid数据库连接池, 只需要引入相关依赖即可。
XML
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid-spring-boot-3-starter</artifactId>
<version>1.2.21</version>
</dependency>
如果SpringBoot版本为2.X,使用druid-spring-boot-starter依赖。
XML
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid-spring-boot-starter</artifactId>
<version>1.1.17</version>
</dependency>


7.总结
7.1 MySQL开发企业规范


7.2 #{}和${}区别(面试题)


