Mybatis和Mybatis Plus
什么是Mybatis
SSM项目:就是Spring,SpringMVC,Mybatis
创建SpringBoot项目可以自动添加Spring和SpringMvc
我们只需要添加Mybatis即可
Mybatis是一个能够简化数据库编程的框架
底层运行的是jdbc代码,但是我们通过Mybatis实现数据库操作的编码量会大量减少
Spring整合Mybatis之后,只需要在指定位置创建一个接口就可以自动根据方法的声明,生成实现语句,无序程序员编写
创建SSM项目
创建springboot项目.命名mybatis,添加依赖
<!-- 下面的依赖是添加Mybatis框架的依赖 -->
<dependency>
<groupId>org.mybatis.spring.boot</groupId>
<artifactId>mybatis-spring-boot-starter</artifactId>
<version>2.1.2</version>
</dependency>
<!-- 添加mysql连库驱动类 Mysql Driver -->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<scope>runtime</scope>
</dependency>
application.properties
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
spring.datasource.url=jdbc:mysql://localhost:3306/tedu_ums?characterEncoding=utf8&useSSL=false&serverTimezone=Asia/Shanghai&rewriteBatchedStatements=true
spring.datasource.username=root
spring.datasource.password=root
创建一个专门编写操作数据接口\类的包, 这个包叫mapper
需要在SpringBoot启动类中指定这个包是连接数据库进行操作的包
实际上是告诉Mybatis这个包里是连接数据库的
数据库初始化, 导入数据库sql
CREATE DATABASE tedu_ums;
USE tedu_ums;
CREATE TABLE t_user (
id INT(11) AUTO_INCREMENT COMMENT '用户id',
username VARCHAR(20) UNIQUE NOT NULL COMMENT '用户名',
password VARCHAR(20) NOT NULL COMMENT '密码',
age INT COMMENT '年龄',
phone VARCHAR(20) COMMENT '手机号码',
email VARCHAR(20) COMMENT '电子邮箱',
PRIMARY KEY (id)
) DEFAULT CHARSET=utf8;
INSERT INTO t_user (username, password, phone, age, email) VALUES
('Frank01', '1234', '13800138001', 28, 'frank01@163.com'),
('Frank04', '1234', '13800138004', 33, 'frank04@163.com'),
('Frank05', '1234', '13800138005', 21, 'frank05@163.com'),
('Frank09', '1234', '13800138009', 26, 'frank09@163.com'),
('Frank06', '1234', '13800138006', 29, 'frank06@163.com'),
('Frank11', '1234', '13800138011', 24, 'frank11@163.com'),
('Frank12', '1234', '13800138012', 23, 'frank12@163.com'),
('Frank07', '1234', '13800138007', 31, 'frank07@163.com'),
('Frank08', '1234', '13800138008', 22, 'frank08@163.com'),
('Frank02', '1234', '13800138002', 27, 'frank02@163.com'),
('Frank03', '1234', '13800138003', 32, 'frank03@163.com'),
('Frank10', '1234', '13800138010', 30, 'frank10@163.com'),
('Frank13', '1234', '13800138013', 25, 'frank13@163.com');
上面的sql语句在数据库中运行
我们创建了一个数据库叫tedu_ums
数据库中创建了表t_user
表中有若干数据
这个表在java中要对应一个实体类这个实体类要由我们创建
我们创建一个包:model
如果要使用Lombok实现准备好pom.xml文件的依赖
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</dependency>
包中创建一个类User代码如下
//这是一个实体类,实体类对应数据库中的t_user表
//这个类中的所有属性名必须和表中的列名一致
@Data
public class User {
private Integer id;
private String username;
private String password;
private Integer age;
private String phone;
private String email;
}
Mybatis的初步使用
我们先使用Mybatis实现一个最简单的查询操作
查询指定id的用户的用户名
这样的查询sql语句为 select username from t_user where id=10
实现这样的查询只需要在mapper包中创建一个接口UserMapper
在这个接口中创建一个方法,并声明要执行的sql语句即可
代码如下
//这个接口就是Mybatis框架要生成实现的接口了
public interface UserMapper {
//这个注解表示要执行一个查询操作
//注解的()里写要执行的sql语句
@Select("select username from t_user where id=10")
//这个注解紧随一个方法的声明,当前操作需要指定返回值类型和方法名
String getUsernameById();
}
测试类中编写代码运行
@Resource
UserMapper userMapper;
@Test
void byId() {
String username=userMapper.getUsernameById();
System.out.println(username);
}
Mybatis工作运行原理
在配置文件中,我们指定了cn.tedu.mybatis.mapper是Mybatis控制数据库所在代码的包
Mybatis框架中有一个功能特别强大的类:SqlSessionFactory
这个类会根据指定包中接口中声明方法的自动实现这个接口的方法生成jdbc代码,并生成实现类对象,最后注入到Spring容器中
使用Mybatis实现简单CRUD(增删改查)
按id条件查询
UserMapper接口中新增一个方法
//实际开发中查询尽量避免使用*
//如果条件是可变的,那么需要使用#{xx}来占位 xx位置内容可变
@Select("select id,username,password,age,phone,email " +
" from t_user where id=#{id}")
//根据查询的内容确定一个合适的返回值类型
//User是我们对应数据库表定义的实体类
//数据库表中的列名和User类中的属性名完全一致
//底层实际上是调用User类的get或set方法实现的
//例如我们查询出了数据库中的id列,
// 就会调用User对象的setId方法为id属性赋值
// 以此类推User对象的所有属性就都有值了
//当前我们的sql语句有一个#{}占位符,就需要传入一个参数
User getUserById(Integer id);
添加测试代码
实现按id查询User对象
@Test
void getUser(){
User user=userMapper.getUserById(5);
System.out.println(user);
}
实现查询全部User对象
在UserMapper中添加如下代码
@Select("select * from t_user")
List<User> getUsers();
测试类测试
@Test
void getUsers(){
List<User> users=userMapper.getUsers();
for(User u:users){
System.out.println(u);
}
}
新增功能
使用insert数据对数据库表插入一条数据
sql语句新增一条的代码如下
insert into t_user values(null,?,?,?,?,?)
在UserMapper接口中编写代码如下
//新增一行数据
@Insert("insert into t_user values(null,#{username}," +
"#{password},#{age},#{phone},#{email})")
// 增删改代码返回的都是受影响的行数即int或Integer类型
// 方法的参数user应该包含#{}中要求的属性值
// 底层会调用user对象的get方法为#{}赋值
// 例如#{username}就会调用user对象的getUsername方法
// 获得user对象的username属性值
Integer insert(User user);
测试代码如下
//新增一行User信息
@Test
void insert(){
User user=new User();
user.setUsername("孙悟空");
user.setPassword("123");
user.setAge(600);
user.setPhone("110");
user.setEmail("110@qq.com");
int num=userMapper.insert(user);
System.out.println(num);
System.out.println("新增user的id:"+user.getId());
}
新增的代码运行后数据库确实能够新增一个用户
但是java代码中完成新增后,User对象的id属性仍然为空
如果想新增到数据库后user对象的id同时被赋值就需要改写新增方法如下
@Insert("insert into t_user values(null,#{username}," +
"#{password},#{age},#{phone},#{email})")
//@Options表示要设置当前sql操作的细节
//useGeneratedKeys = true表示要获得生成的主键
//keyProperty = "id"表示当前user对象对应主键的属性是id
@Options(useGeneratedKeys = true,keyProperty = "id")
Integer insert(User user);
再次运行上面的测试输出id就不会是空了
实现修改数据的功能
如果需求根据用户的id修改用户的各列的值sql语句为
update t_user set username=?,password=?,age=?,phone=?,email=?
where id=?
UserMapper添加一个修改方法,sql语句将?替换为#{}
代码如下
//修改User的各列
@Update("update t_user set username=#{username}," +
"password=#{password},age=#{age},phone=#{phone}," +
"email=#{email} where id=#{id}")
Integer updateUser(User user);
测试代码如下
@Test
void update(){
User user=userMapper.getUserById(16);
//上面是查询的id为16的行,user对象中所有属性都有值
user.setUsername("小白龙");
int num=userMapper.updateUser(user);
System.out.println(num);
}
上面实现的修改功能是可以修改除id之外一行数据的任何列的
我们将这样的修改成为全行修改
这样的修改有一个缺点,就是不能固定业务逻辑,在修改username时也要提供除username之外所有属性的值,使用起来比较麻烦
如果我希望实现一个根据用户id修改密码的业务,最好直接编写一个方法更加简单
UserMapper接口中添加一个方法,根据用户id修改用户密码
update t_user set password=? where id=?
接口中代码编写如下
@Update("update t_user set password=#{password} where id=#{id}")
//下面方法的参数Integer id,String password
// id底层会匹配#{id} password会匹配给#{password}
// 如果一个sql操作只有一个参数同时只有一个占位符,名字是可以不匹配的
Integer updatePassword(Integer id,String password);
测试类测试代码
//根据id修改用户密码
@Test
void updatePassword(){
//将id为14的用户的密码修改为888888
int num=userMapper.updatePassword(14,"888888");
System.out.println(num);
}
当项目没有使用SpringBoot框架来搭建SSM时
遇到上面的查询参数中要添加注解
@Update("update t_user set password=#{password} where id=#{id}")
// 当项目没有使用SpringBoot框架来搭建SSM时
// 我们就需要使用原生的Mybatis来进行占位符的匹配
// 这种情况下我们必须启用一个注解来实现绑定关系
Integer updatePassword(@Param("id") Integer xx,
@Param("password") String yy);
删除功能
删除实际上是比较简单的我们来一起实现以下即可
UserMapper接口中添加根据用户id删除用户的方法
代码如下
@Delete("delete from t_user where id=#{id}")
//这个方法的参数使用了hehe 因为是一个参数一个占位符,所以随意命名
Integer deleteUserById(Integer hehe);
Mybatis Plus
Mybatis Plus框架是在Mybatis的基础上 又新增了一些功能
进一步简化数据库开发的衍生框架
我们上面学习的所有知识MybatisPlus都支持
我们将现在项目添加的Mybatis的依赖修改为MybatisPlus的
体会一下MybatisPlus的新功能
只需要修改pom.xml即可
<!-- 下面的依赖是添加Mybatis框架的依赖 -->
<!--
<dependency>
<groupId>org.mybatis.spring.boot</groupId>
<artifactId>mybatis-spring-boot-starter</artifactId>
<version>2.1.2</version>
</dependency>
-->
<!-- 添加mybatisPlus的依赖 -->
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-boot-starter</artifactId>
<version>3.3.1</version>
</dependency>
application.properties文件和SpringBoot启动类不用修改
当我们的项目支持了Mybatis之后
我们操作数据库的代码就更加简单了
我们可以定义一个接口,让这个接口继承BaseMapper的父接口
这样当前对应的实体类可以自动生成简单的CRUD操作,无需我们在编写任何代码
下面我们就来写一下
mapper包创建新接口UserMapperPlus
代码如下
@Repository
//extends是继承的意思,表示当前接口继承一个父接口
//BaseMapper 是MybatisPlus框架提供的接口,其中包含着一系列基本的增删改查操作
//只需要在BaseMapper的<>中指定这个类型,MybatisPlus就会针对这个类生成代码
public interface UserMapperPlus extends BaseMapper<User> {
}
User实体类声明对应的表名
@Data
//下面注解表示当前实体类对应的表
@TableName("t_user")
public class User {
private Integer id;
private String username;
private String password;
private Integer age;
private String phone;
private String email;
}
测试类代码如下
@Autowired
UserMapperPlus userMapper;
@Test
void byId(){
User user=userMapper.selectById(15);
System.out.println(user);
}
@Test
void users(){
List<User> list=userMapper.selectList(null);
for(User u:list){
System.out.println(u);
}
}
@Test
void other(){
// 新增
User user=new User();
//省略赋值内容
int num=userMapper.insert(user);
// 修改(我么实现过得全表修改)
user.setUsername("小白龙");
num=userMapper.updateById(user);
// 按id删除
num= userMapper.deleteById(11);
}
既然基本的增删改成都已经实现了
那么我怎么查看它内部执行的sql语句呢?
SpringBoot内部支持了日志系统
我们需要做的就是让Mybatis\MybatisPlus底层输出的日志显示在我们的控制台上
我们可以在application.properties文件中使用配置
规定哪些类中的什么级别的日志信息要输出到SpringBoot控制台上
# 表示设置当前项目cn.tedu.mybatis包下的所有类的日志输出级别是debug
# 意思是程序中输出debug以及debug级别以上的所有日志都会输出到控制台
logging.level.cn.tedu.mybatis=debug
logging.level.cn.tedu.mybatis.mapper=trace
要想在程序中使用日志需要在类上添加一个注解,以测试类为例,代码如下
@SpringBootTest
//如果想在当前类记录日志,就添加这个注解
// 添加这个注解之后当前类的任何方法都可以使用log对象记录日志
@Slf4j
public class PlusTest {
@Test
void byId(){
User user=userMapper.selectById(15);
System.out.println(user);
//记录日志的代码!!!!!!!!!!!!
log.debug("error日志输出");
}
//其它代码略
}
小结
我们学习了怎么添加Mybatis的支持
学习了怎么在mapper文件夹中创建编写UserMapper实现基本增删改查操作
学习了MybatisPlus,进一步减少了代码的编写直接使用其提供的增删改查方法
日志门槛的设置
日志记录的等级
高: fatal
error
warn
info
debug
低 trace
SpringBoot默认情况下只会将error以上级别的信息显示到控制台
Xml文件映射Mapper接口
xml头文件mybatis的官网找最新头文件 https://mybatis.org/mybatis-3/getting-started.html
Mybatis框架中如果需求比较复杂的sql语句时,将sql语句编写在接口中就有些功能不足了
Mybatis支持使用xml文件来实现更加复杂的业务逻辑的查询
我们创建一个xml文件放置在规定位置,就可以和Mapper进行映射连接
实现xml文件中编写的sql语句能够在Mapper文件中调用的功能
步骤1:
在resources文件夹下创建一个mapper文件夹,名字只能是mapper
步骤2:
在创建好的文件夹中创建一个xml文件,文件名随意但是一般对应Mapper接口
步骤3:
在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">
<!-- namespace 属性执行映射到 UserMapperPlus接口 -->
<mapper namespace="cn.tedu.mybatis.mapper.UserMapperPlus">
<!-- id 属性映射到UserMapperPlus接口中的test方法
resultType 映射到test返回值的类型-->
<select id="test" resultType="java.lang.String">
SELECT username from t_user where id=1
</select>
</mapper>
步骤4:
在UserMapperPlus接口中编写一个对应上面xml文件中的查询的方法
代码如下
public interface UserMapperPlus extends BaseMapper<User> {
//下面写的方法是要映射xml文件中的查询的
//这样的方法不需要编写任何注解
//只需要方法的名称和xml文件中对应的查询的id一致即可
String test();
}
步骤5:
在测试类中调用我们编写的xml方法
代码如下
@Test
void xml(){
String username=userMapper.test();
System.out.println(username);
}