SpringBoot整合Mybatis_plus笔记
创建数据库和表
use mybatis; drop table if exists book; CREATE TABLE `Book` ( `id` int(50) NOT NULL COMMENT '图书id', `type` varchar(100) NOT NULL COMMENT '图书类型', `name` varchar(30) NOT NULL COMMENT 图书名, `author` varchar(30) NOT NULL COMMENT '作者' ) ENGINE=InnoDB DEFAULT CHARSET=utf8; --在真实发展中,version(乐观
锁),deleted(逻辑删除),gmt_create,gmt_modified
2、导入依赖
<?xml version="1.0" encoding="UTF-8"?> <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>2.7.0</version> <relativePath/> <!-- lookup parent from repository --> </parent> <groupId>com.czb</groupId> <artifactId>mybatis_plus</artifactId> <version>0.0.1-SNAPSHOT</version> <name>mybatis_plus</name> <description>mybatis_plus</description> <properties> <java.version>17</java.version> </properties> <dependencies> <!--数据库驱动--> <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> </dependency> <!--lombok--> <dependency> <groupId>org.projectlombok</groupId> <artifactId>lombok</artifactId> </dependency> <!--mybatis-plus--> <dependency> <groupId>com.baomidou</groupId> <artifactId>mybatis-plus-boot-starter</artifactId> <version>3.4.3.1</version> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-test</artifactId> <scope>test</scope> </dependency> </dependencies> <build> <plugins> <plugin> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-maven-plugin</artifactId> </plugin> </plugins> </build> </project>
3、配置application.properties文件
#数据可配置
spring.datasource.username=root
spring.datasource.password=root
spring.datasource.url=jdbc:mysql://localhost:3306/mybatis?characterEncoding=utf-8&useSSL=false&useUnicode=true&serverTimezone=GMT%2B8
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
#日志配置
mybatis-plus.configuration.log-impl=org.apache.ibatis.logging.stdout.StdOutImpl
4、创建实体类
package com.czb.pojo;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
@Data
@AllArgsConstructor
@NoArgsConstructor
public class Book {
private Integer id;
private String type;
private String name;
private String author;
}
5、创建***Mapper接口类
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.czb.pojo.Book;
import org.springframework.stereotype.Repository;
@Repository //代表持久层
public interface BookMapper extends BaseMapper<Book> {
//BookMapper继承了BaseMapper之后就有了CRUD方法
}
6、启动类
package com.czb;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
//一般是自动生成的,但是扫描需要自己添加
@MapperScan("com.czb.mapper")
@SpringBootApplication
public class MybatisPlusApplication {
public static void main(String[] args) {
SpringApplication.run(MybatisPlusApplication.class, args);
}
}
7、配置类
package com.czb.config;
import com.baomidou.mybatisplus.annotation.DbType;
import com.baomidou.mybatisplus.extension.plugins.MybatisPlusInterceptor;
import com.baomidou.mybatisplus.extension.plugins.inner.OptimisticLockerInnerInterceptor;
import com.baomidou.mybatisplus.extension.plugins.inner.PaginationInnerInterceptor;
import com.baomidou.mybatisplus.extension.plugins.pagination.optimize.JsqlParserCountOptimize;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.transaction.annotation.EnableTransactionManagement;
@MapperScan("com.czb.mapper")
@EnableTransactionManagement
@Configuration //配置类
public class MybatisPlusConfig {
//注册乐观锁插件
@Bean
public OptimisticLockerInnerInterceptor optimisticLockerInnerInterceptor(){
return new OptimisticLockerInnerInterceptor();
}
//注册分页插件
@Bean
public MybatisPlusInterceptor mybatisPlusInterceptor() {
MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();
interceptor.addInnerInterceptor(new PaginationInnerInterceptor(DbType.MYSQL));
interceptor.addInnerInterceptor(new OptimisticLockerInnerInterceptor());
return interceptor;
}
}
8、测试类
package com.czb;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.czb.mapper.BookMapper;
import com.czb.pojo.Book;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import java.util.List;
@SpringBootTest
class MybatisPlusApplicationTests {
@Autowired
private BookMapper bookMapper;
@Test
void contextLoads() {
//测试插入
// bookMapper.insert(new Book(1,"历史","红楼梦","曹雪芹"));
// bookMapper.insert(new Book(2,"历史","水浒传","施耐庵"));
// bookMapper.insert(new Book(3,"历史","西游记","吴承恩"));
//测试查询
// List<Book> Book = bookMapper.selectList(null);
//新的循环输出方法
// Book.forEach(System.out::println);
//测试分页查询
Page<Book> page = new Page<>(2,2);
bookMapper.selectPage(page,null);
page.getRecords().forEach(System.out::println);
//注意更新操作,updateById(book)参数是
Book book = new Book();
book.setId(1L);
book.setType("小说");
bookMapper.updateById(book);
}
}
2、一些功能
1、分页查询日志
==> Preparing: SELECT COUNT(*) FROM book
==> Parameters:
<== Columns: COUNT(*)
<== Row: 3
<== Total: 1
==> Preparing: SELECT id,type,name,author FROM book LIMIT ?,?
==> Parameters: 2(Long), 2(Long)
底层还是使用的Limit,注意先是把所有的都查了出来,然后再进行的分页。
2、主键生成策略
雪花算法组成
Twitter的开源SnowFlake算法用来生成64位的ID,刚好可以用long整型存储,能够用于分布式系统中生产唯一的ID, 并且生成的ID有大致的顺序。 在这次实现中,生成的64位ID可以分成5个部分:0 - 41位时间戳 - 5位数据中心标识 - 5位机器标识 - 12位序列号 - 最后一位符号位为0,不会出现重复;
我们需要配置主键自增:
1.在实体类字段上@TableId(type = IdType.ASSIGN_ID)
2.数据库字段一定要是自增!
CREATE TABLE `Book` (
`id` bigint(20) PRIMARY KEY auto_increment NOT NULL COMMENT'图书id',
`type` varchar(100) NOT NULL COMMENT '图书类型',
`name` varchar(30) NOT NULL COMMENT '图书名字',
`author` varchar(30) NOT NULL COMMENT '作者'
) ENGINE=InnoDB DEFAULT CHARSET=utf8
public class Book {
@TableId(type = IdType.ASSIGN_ID) //雪花算法ASSIGN_ID
private Long id;
private String type;
private String name;
private String author;
}
==> Preparing: INSERT INTO book ( id, type, name, author ) VALUES ( ?, ?, ?, ? )
==> Parameters: 1537719556296867841(Long), 历史(String), 西游记(String), 吴承恩(String)
<== Updates: 1
Closing non transactional SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@d9f5fce]
Book(id=1537719556296867841, type=历史, name=西游记, author=吴承恩)
==> Preparing: INSERT INTO book ( id, type, name, author ) VALUES ( ?, ?, ?, ? )
==> Parameters: 1537719849680101378(Long), 历史(String), 三国演义(String), 罗贯中(String)
<== Updates: 1
Closing non transactional SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@65859b44]
Book(id=1537719849680101378, type=历史, name=三国演义, author=罗贯中)
3、乐观锁
乐观锁:顾名思义十分乐观,总是认为不会出现问题,无论干什么都不上锁,如果出现了问题,再次更新值测试
悲观锁:总是认为会出现问题,无论干什么都会上锁,再去操作
//注册乐观锁插件
@Bean
public OptimisticLockerInnerInterceptor optimisticLockerInnerInterceptor(){
return new OptimisticLockerInnerInterceptor();
}
乐观锁实现方式:
- 取出记录时,获取当前version
- 更新时,带上这个version
- 执行更新时,set version = newVersion where version = oldVersion
- 如果version不对,则更新失败
乐观锁;1.先查询,获得版本号 version = 1
--A
update user set name = "nnnnn",version = version + 1
where id = 2 and version = 1
--B线程抢先完成,version = 2会导致A更新失败 详情看高并发编程
update user set name = "nnnnn",version = version + 1
where id = 2 and version = 1
测试:
mysql表添加字段version
实体类添加字段version
@Version
private Integer version;
配置类中注册插件
//注册乐观锁插件
@Bean
public OptimisticLockerInnerInterceptor optimisticLockerInnerInterceptor(){
return new OptimisticLockerInnerInterceptor();
}
测试
@Test
public void test1(){
//线程1
Book book = bookMapper.selectById(1L);
book.setType("文学");
//线程2
Book book2 = bookMapper.selectById(1L);
book2.setType("nnnnn");
bookMapper.updateById(book2);
//执行更新操作
bookMapper.updateById(book);
}
4、逻辑删除
物理删除:从数据库直接移除
逻辑删除:数据库中没有删除,而是通过一个变量使其失效!deleted = 0 >>>>deleted = 1
管理员可以查看被删除的记录!防止数据丢失,类似于回收站!
实体类增加:
@TableLogic //逻辑删除
private Integer deleted;
config配置中不需要再注册!
application.properties中添加:
mybatis-plus.global-config.db-config.logic-delete-value=1
mybatis-plus.global-config.db-config.logic-not-delete-value=0
测试
@Test
public void test2(){
bookMapper.deleteById(1L);
}
//逻辑删除执行更新操作
==> Preparing: UPDATE book SET deleted=1 WHERE id=? AND deleted=0
==> Parameters: 1(Long)
<== Updates: 1
数据库中记录还在,deleted变为1:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-da9En3sQ-1655811700770)(C:\Users\DIY\AppData\Roaming\Typora\typora-user-images\image-20220620110725530.png)]
查询时会自动过滤deleted = 1的数据,所以查询不出来,需要管理员权限;
5、自动填充
创建时间、修改时间!这些操作都是自动完成的,不希望手动更新!
方式一:数据库级别
1、在表中新增字段create_time,uadate_time
2、同步实体类
private Date create_time;
private Date update_time;
3、测试
@Test
public void test2(){
Book book = new Book();
book.setId(2L);
book.setName("三体");
book.setType("科幻");
book.setAuthor("刘慈欣");
bookMapper.updateById(book);
}
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-VLJcQsAE-1655811700772)(C:\Users\DIY\AppData\Roaming\Typora\typora-user-images\image-20220620142041882.png)]
方式二:代码级别
1、删除数据库的默认值、更新操作!
2、实体类字段属性上需要增加注解
// 字段添加填充内容
@TableField(fill = FieldFill.INSERT)
private Date createTime;
@TableField(fill = FieldFill.INSERT_UPDATE)
private Date updateTime;
3、编写处理器来处理这个注解即可!
package com.czb.handler;
import com.baomidou.mybatisplus.core.handlers.MetaObjectHandler;
import lombok.extern.slf4j.Slf4j;
import org.apache.ibatis.reflection.MetaObject;
import org.springframework.stereotype.Component;
import java.util.Date;
@Slf4j
@Component
public class MyMetaObjectHandler implements MetaObjectHandler {
//插入时的填充策略
@Override
public void insertFill(MetaObject metaObject) {
log.info("start insert fill......");
this.setFieldValByName("create_time",new Date(),metaObject);
this.setFieldValByName("update_time",new Date(),metaObject);
}
//更新时的填充策略
@Override
public void updateFill(MetaObject metaObject) {
log.info("start update fill......");
this.setFieldValByName("update_time",new Date(),metaObject);
}
}
4、测试
6、性能分析插件
我们在平时的开发中,会遇到一些慢sql。测试! druid,
作用:性能分析拦截器,用于输出每条 SQL 语句及其执行时间
MP也提供性能分析插件,如果超过这个时间就停止运行!
1、导入依赖
<dependency>
<groupId>p6spy</groupId>
<artifactId>p6spy</artifactId>
<version>3.9.1</version>
</dependency>
2、设置开发环境application.properties
spring.datasource.username=root
spring.datasource.password=root
spring.datasource.url=jdbc:p6spy:mysql://localhost:3306/mybatis?characterEncoding=utf-8&useSSL=false&useUnicode=true&serverTimezone=GMT%2B8
spring.datasource.driver-class-name=com.p6spy.engine.spy.P6SpyDriver
3、spy.properties
modulelist=com.baomidou.mybatisplus.extension.p6spy.MybatisPlusLogFactory,com.p6spy.engine.outage.P6OutageFactory #
自定义日志打印 logMessageFormat=com.baomidou.mybatisplus.extension.p6spy.P6SpyLogger #日志输出到控制台 appender=com.baomidou.mybatisplus.extension.p6spy.StdoutLogger # 使用日志系统记录 sql #appender=com.p6spy.engine.spy.appender.Slf4JLogger # 设置 p6spy driver 代理 deregisterdrivers=true # 取消JDBC URL前缀 useprefix=true # 配置记录 Log 例外,可