一、Mybatis plus
意义:
为简化而生
- 无侵入:只做增强不做改变,引入它不会对现有工程产生影响,如丝般顺滑
- 损耗小:启动即会自动注入基本 CURD,性能基本无损耗,直接面向对象操作
- 强大的 CRUD 操作:内置通用 Mapper、通用 Service,仅仅通过少量配置即可实现单表大部分 CRUD 操作,更有强大的条件构造器,满足各类使用需求
- 支持 Lambda 形式调用:通过 Lambda 表达式,方便的编写各类查询条件,无需再担心字段写错
- 支持主键自动生成:支持多达 4 种主键策略(内含分布式唯一 ID 生成器 - Sequence),可自由配置,完美解决主键问题
- 支持 ActiveRecord 模式:支持 ActiveRecord 形式调用,实体类只需继承 Model 类即可进行强大的 CRUD 操作
- 支持自定义全局通用操作:支持全局通用方法注入( Write once, use anywhere )
- 内置代码生成器:采用代码或者 Maven 插件可快速生成 Mapper 、 Model 、 Service 、 Controller 层代码,支持模板引擎,更有超多自定义配置等您来使用
- 内置分页插件:基于 MyBatis 物理分页,开发者无需关心具体操作,配置好插件之后,写分页等同于普通 List 查询
- 分页插件支持多种数据库:支持 MySQL、MariaDB、Oracle、DB2、H2、HSQL、SQLite、Postgre、SQLServer 等多种数据库
- 内置性能分析插件:可输出 SQL 语句以及其执行时间,建议开发测试时启用该功能,能快速揪出慢查询
- 内置全局拦截插件:提供全表 delete 、 update 操作智能分析阻断,也可自定义拦截规则,预防误操作
DROP TABLE IF EXISTS user;
CREATE TABLE user
(
id BIGINT(20) NOT NULL COMMENT ‘主键ID’,
name VARCHAR(30) NULL DEFAULT NULL COMMENT ‘姓名’,
age INT(11) NULL DEFAULT NULL COMMENT ‘年龄’,
email VARCHAR(50) NULL DEFAULT NULL COMMENT ‘邮箱’,
PRIMARY KEY (id)
);支持数据库
任何能使用 MyBatis 进行 CRUD, 并且支持标准 SQL 的数据库,具体支持情况如下,如果不在下列表查看分页部分教程 PR 您的支持。
- MySQL,Oracle,DB2,H2,HSQL,SQLite,PostgreSQL,SQLServer,Phoenix,Gauss ,ClickHouse,Sybase,OceanBase,Firebird,Cubrid,Goldilocks,csiidb
- 达梦数据库,虚谷数据库,人大金仓数据库,南大通用(华库)数据库,南大通用数据库,神通数据库,瀚高数据库
1、快速入门
构建一个SpringBoot工程
- 导入依赖
注意!!!mybatis和plus版本只能引入其中一个版本,不然会失效
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
</dependency>
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-boot-starter</artifactId>
<version>3.0.5</version>
</dependency>
- 创建表 ```sql DROP TABLE IF EXISTS user;
CREATE TABLE user ( id BIGINT(20) NOT NULL COMMENT ‘主键ID’, name VARCHAR(30) NULL DEFAULT NULL COMMENT ‘姓名’, age INT(11) NULL DEFAULT NULL COMMENT ‘年龄’, email VARCHAR(50) NULL DEFAULT NULL COMMENT ‘邮箱’, PRIMARY KEY (id) );
DELETE FROM user;
INSERT INTO user (id, name, age, email) VALUES (1, ‘Jone’, 18, ‘test1@baomidou.com’), (2, ‘Jack’, 20, ‘test2@baomidou.com’), (3, ‘Tom’, 28, ‘test3@baomidou.com’), (4, ‘Sandy’, 21, ‘test4@baomidou.com’), (5, ‘Billie’, 24, ‘test5@baomidou.com’);
3. 编写实体类以及实体类Mapper接口
```java
//继承BaseMapper plus中的接口
// 处理哪一个实体类就所使用该实体类的泛型
@Repository//代表持久层
@Mapper
public interface UserMapper extends BaseMapper<User> {
//此时所有的CRUD全部完成
}
此时
这些方法都来自于父类BaseMapper,当然我们自己也可以编写方法查询
- 编写测试方法
@Slf4j
@SpringBootTest
class MybatisPlusApplicationTests {
@Autowired
private UserMapper userMapper;
@Test
void contextLoads() {
//Wrapper<T> 是一个条件构造器 查询所有没有条件,填写null
List<User> users = userMapper.selectList(null);
log.info("所有用户是{}",users);
}
}
# 打印日志
mybatis-plus:
configuration:
log-impl: org.apache.ibatis.logging.stdout.StdOutImpl
2、CRUD
主键生成策略
snowflake雪花算法 (推特)
【https://www.cnblogs.com/haoxinyue/p/5208136.html】
snowflake是Twitter开源的分布式ID生成算法,结果是一个long型的ID。其核心思想是:使用41bit作为毫秒数,10bit作为机器的ID(5个bit是数据中心,5个bit的机器ID),12bit作为毫秒内的流水号(意味着每个节点在每毫秒可以产生 4096 个 ID),最后还有一个符号位,永远是0。具体实现的代码可以参看https://github.com/twitter/snowflake。雪花算法支持的TPS可以达到419万左右(2^22*1000)。
@TableId
标注在实体类作为主键的属性上
相应的type配置
- @TableId(type=IdType.NONE) 自增
- 数据库主键字段必须是自增的
其余的
public enum IdType {
AUTO(0),//数据库ID自增
NONE(1),//未设置主键自增
INPUT(2),//手动输入
ASSIGN_ID(3),//
ASSIGN_UUID(4);//全局唯一ID
更新操作
@Test
void Update(){
User user = new User(1471747870506700801L,"23232柱",23,"101001");
int insert = userMapper.updateById(user);
System.out.println(insert);
}
内置动态SQL
自动填充
创建时间、修改时间!这些操作都是一遍自动化完成的,不希望手动更新 阿里巴巴开发手册: 所有数据库表: gmt_create,gmt_modified几乎所有的表都要配置上!而且自动化
方式一(不建议)
数据库级别
create table user
(
id bigint not null comment '主键ID'
primary key,
name varchar(30) null comment '姓名',
age int null comment '年龄',
email varchar(50) null comment '邮箱',
# 时间单位 默认为当前时间戳
gmt_create datetime default current_timestamp,
gmt_modified datetime default current_timestamp
);
更改实体类
public class User {
@TableId(type = IdType.NONE)
private Long id;
private String name;
private Integer age;
private String email;
private Date gmtCreate;
private Date gmtModified;
}
方式二
代码级别
//插入时间更新 @TableField(fill = FieldFill.INSERT) private Date gmtCreate; //更改时间更新 @TableField(fill = FieldFill.UPDATE) private Date gmtModified;
3. 获取填充
```java
@Component//注册到SpringBoot中
public class MyMetaObjectHandler implements MetaObjectHandler {
@Override//插入数据时填充字段
public void insertFill(MetaObject metaObject) {
log.info("start insert fill ....");
// 参数一 字段名 二、字段值 三、要给哪个数据处理
this.setFieldValByName("gmtCreate",new Date(),metaObject);
this.setFieldValByName("gmtModified",new Date(),metaObject);
}
@Override//更改数据时填充字段
public void updateFill(MetaObject metaObject) {
log.info("start update fill ....");
this.setFieldValByName("gmtModified",new Date(),metaObject);
}
}
乐观锁
对乐观锁和悲观锁的文章https://www.jianshu.com/p/d2ac26ca6525
乐观锁: 不会认为出什么问题,干什么都不会先上锁!出了问题就更新值测试 悲观锁:悲观,认为干什么都会出问题,无论干什么,都会先上锁再操作
alter table user add version int default 1;
线程A和线程B并发 同时更改一条数据,线程A访问之后将version数值+1,之后线程B发现version数值匹配不上,就放弃更改以此保障线程的安全
同时实体类同步
//这个注解代表乐观锁
@Version
private Integer version;
添加拦截器
// Spring Boot 方式
@Configuration
@MapperScan("按需修改")
public class MybatisPlusConfig {
/**
* 旧版
*/
@Bean
public OptimisticLockerInterceptor optimisticLockerInterceptor() {
return new OptimisticLockerInterceptor();
}
/**
* 新版
*/
@Bean
public MybatisPlusInterceptor mybatisPlusInterceptor() {
MybatisPlusInterceptor mybatisPlusInterceptor = new MybatisPlusInterceptor();
mybatisPlusInterceptor.addInnerInterceptor(new OptimisticLockerInnerInterceptor());
return mybatisPlusInterceptor;
}
}
分页查询
1.配置组件
@MapperScan("mybatisplus.mapper")
@Configuration//配置组件
@EnableTransactionManagement//开启事务,默认开启
public class MybatisPlusVersion {
//@Bean//返回乐观锁拦截器组件
@Bean
public MybatisPlusInterceptor mybatisPlusInterceptor() {
MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();
interceptor.addInnerInterceptor(new OptimisticLockerInnerInterceptor());
return interceptor;
}
/**
* 新的分页插件,一缓和二缓遵循mybatis的规则,需要设置 MybatisConfiguration#useDeprecatedExecutor = false 避免缓存出现问题(该属性会在旧插件移除后一同移除)
*/
@Bean
public MybatisPlusInterceptor mybatisPlusInterceptorPage() {
MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();
interceptor.addInnerInterceptor(new PaginationInnerInterceptor(DbType.H2));
return interceptor;
}
}
- 查询
@Test
void pag(){
//获取页
Page<User> objectPage = new Page<>(2,3);
Page<User> userPage = userMapper.selectPage(objectPage, null);
userPage.getRecords().forEach(System.out::println);
}
逻辑删除
物理删除:从数据库中直接移除 逻辑删除:在数据库中没有移除,通过程序中的变量让他失效 delede=0=>delete=1
管理员可以查看被删除的记录,防止数据丢失,类似于回收站
添加一个字段delete
alter table user add luo_ji int default 0;
配置文件
mybatis-plus:
global-config:
db-config:
logic-delete-field: flag # 全局逻辑删除的实体字段名(since 3.3.0,配置后可以忽略不配置步骤2)
logic-delete-value: 1 # 逻辑已删除值(默认为 1)
logic-not-delete-value: 0 # 逻辑未删除值(默认为 0)
注解:
@TableLogic
private Integer luoJi;
执行删除语句
执行SQL分析插件
新版官方已经移除,参见官方文档
条件查询器 Warpper
支持混合SQL查询
QueryWrapper<User> userQueryWrapper = new QueryWrapper<>();
userQueryWrapper.inSql("id","select id from user where id < 3");
userMapper.selectList(userQueryWrapper).forEach(System.out::println);
代码生成器
新版
- 导入依赖
全局配置方案<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-generator</artifactId>
<version>3.5.1</version>
</dependency>
https://baomidou.com/pages/981406/#%E5%85%A8%E5%B1%80%E9%85%8D%E7%BD%AE-globalconfig