学完的感觉是:可以代替完成一些简单的CURD代码,复杂的SQL语句也可以用wrapper手动完成,但是感觉写成java代码对于后期维护可能比较费眼睛,不如xml写好完整的sql语句更清晰。不过自动填充、乐观锁、分页查询的功能挺方便,在自动注入的sql代码中也会自动加上去。自动生成基本代码插件也挺好,可以快速生成一个整体代码框架,就不用手动创建了(在非常多的数据库表的情况下就能体现出它的优点了),我们只需要往里面写逻辑代码即可。
Mybatis Plus
可以节省大量时间 所有CRUD代码都可以自动化完成
创建学习环境
1、创建数据库
2、创建User表
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)
);
3、加入数据
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');
4、创建一个普通的springboot项目,导入基本依赖
<dependencies>
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-boot-starter</artifactId>
<version>3.5.1</version>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-jdbc</artifactId>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
CRUD扩展
插入操作
主键生成策略
默认 ID_WORKER 全局唯一id
public enum IdType {
/**
* 数据库ID自增
* <p>该类型请确保数据库设置了 ID自增 否则无效</p>
*/
AUTO(0),
/**
* 该类型为未设置主键类型(注解里等于跟随全局,全局里约等于 INPUT)
*/
NONE(1),
/**
* 用户输入ID
* <p>该类型可以通过自己注册自动填充插件进行填充</p>
*/
INPUT(2),
/* 以下3种类型、只有当插入对象ID 为空,才自动填充。 */
/**
* 分配ID (主键类型为number或string),
* 默认实现类 {@link com.baomidou.mybatisplus.core.incrementer.DefaultIdentifierGenerator}(雪花算法)
*
* @since 3.3.0
*/
ASSIGN_ID(3),
/**
* 分配UUID (主键类型为 string)
* 默认实现类 {@link com.baomidou.mybatisplus.core.incrementer.DefaultIdentifierGenerator}(UUID.replace("-",""))
*/
ASSIGN_UUID(4);
private final int key;
IdType(int key) {
this.key = key;
}
}
雪花算法:
snowflake是Twitter开源的分布式ID生成算法,结果是一个long型的ID。其核心思想是:使用41bit作为
毫秒数,10bit作为机器的ID(5个bit是数据中心,5个bit的机器ID),12bit作为毫秒内的流水号(意味
着每个节点在每毫秒可以产生 4096 个 ID),最后还有一个符号位,永远是0。可以保证几乎全球唯
一!
更新操作
自动填充
创建时间、修改时间,这些操作是自动化完成的,
阿里巴巴开发手册:所有的数据库表:gmt_create、gmt_modified 几乎在所有的表都要配置上,而且需要自动化。
方式一:数据库修改
插入时,两个字段都等于当前时间,插入更新时,update_time更新当前时间
更新测试:
方式二
1、注解 @TableField
2、编写处理器
import java.time.LocalDateTime;
@Slf4j
@Component
public class MyMetaObjectHandler implements MetaObjectHandler {
@Override
public void insertFill(MetaObject metaObject) {
log.info("start insert fill ....");
this.strictInsertFill(metaObject,"createTime", LocalDateTime.class,LocalDateTime.now());
}
@Override
public void updateFill(MetaObject metaObject) {
log.info("start update fill ....");
this.strictUpdateFill(metaObject,"createTime", LocalDateTime.class,LocalDateTime.now());
}
}
注意事项:
- 填充原理是直接给
entity
的属性设置值!!! - 注解则是指定该属性在对应情况下必有值,如果无值则入库会是
null
MetaObjectHandler
提供的默认方法的策略均为:如果属性有值则不覆盖,如果填充值为null
则不填充- 字段必须声明
TableField
注解,属性fill
选择对应策略,该声明告知Mybatis-Plus
需要预留注入SQL
字段 - 填充处理器
MyMetaObjectHandler
在 Spring Boot 中需要声明@Component
或@Bean
注入 - 要想根据注解
FieldFill.xxx
和字段名
以及字段类型
来区分必须使用父类的strictInsertFill
或者strictUpdateFill
方法 - 不需要根据任何来区分可以使用父类的
fillStrategy
方法 - update(T t,Wrapper updateWrapper)时t不能为空,否则自动填充失效
3、测试:
插入
更新
乐观锁
总是认为不会出现问题,无论做什么,都不去上锁,如果出现问题,再次更新值测试
用version检测更新
实现方式;
- 取出记录时,获取当前的version
- 更新时,带上这个version
- 执行更新时,set version = new version where version = oldversion
- 如果version 不对,就更新失败
1、数据库增加version字段
2、同步实体类
@Version //乐观锁 version注解
private Integer version;
3、注册组件
@MapperScan("com.freeze.mybatisplus.mapper")
@EnableTransactionManagement //事务管理
@Configuration //配置类
public class MyBatisPlusConfig {
@Bean
public MybatisPlusInterceptor mybatisPlusInterceptor() {
MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();
interceptor.addInnerInterceptor(new OptimisticLockerInnerInterceptor());//乐观锁插件
return interceptor;
}
}
4、测试
成功更新
//测试乐观锁成功
@Test
void testOptimisticLocker(){
//查询用户信息
User user = userMapper.selectById(1L);
//修改用户信息
user.setName("xibala");
user.setEmail("xibala@qq.com");
//更新
userMapper.updateById(user);
}
失败更新
@Test
void testOptimisticLocker2(){
User user1 = userMapper.selectById(1L);
user1.setName("xibala111");
user1.setEmail("xibala@qq.com");
//模拟另一个 线程插队执行更新操作
User user2 = userMapper.selectById(1L);
user2.setName("xibala222");
user2.setEmail("xibala@qq.com");
userMapper.updateById(user2);
userMapper.updateById(user1);//如果没有乐观锁,就会覆盖插队线程更新的值
}
悲观锁:
总是认为会出现问题,无论做什么都会上锁,再去操作
查询操作
// 测试查询
@Test
public void testSelectById(){
User user = userMapper.selectById(1L);
System.out.println(user);
}
// 测试批量查询!
@Test
public void testSelectByBatchId(){
List<User> users = userMapper.selectBatchIds(Arrays.asList(1, 2, 3));
users.forEach(System.out::println);
}
// 按条件查询之一使用map操作
@Test
public void testSelectByBatchIds(){
HashMap<String, Object> map = new HashMap<>();
// 自定义要查询
map.put("name","狂神说Java");
map.put("age",3);
List<User> users = userMapper.selectByMap(map);
users.forEach(System.out::println);
}
分页查询
1、使用原始limit进行分页
2、pageHelper第三方插件
3、MP其实内置了分页插件
如何使用:
1、添加组件
@MapperScan("com.freeze.mybatisplus.mapper")
@EnableTransactionManagement //事务管理
@Configuration //配置类
public class MyBatisPlusConfig {
@Bean
public MybatisPlusInterceptor mybatisPlusInterceptor() {
MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();
interceptor.addInnerInterceptor(new PaginationInnerInterceptor(DbType.MYSQL));//分页插件
return interceptor;
}
}
2、直接使用Page对象即可!
删除操作
// 测试删除
@Test
public void testDeleteById(){
userMapper.deleteById(1240620674645544965L);
}
// 通过id批量删除
@Test
public void testDeleteBatchId(){
userMapper.deleteBatchIds(Arrays.asList(1240620674645544961L,124062067464554496
2L));
}
// 通过map删除
@Test
public void testDeleteMap(){
HashMap<String, Object> map = new HashMap<>();
map.put("name","狂神说Java");
userMapper.deleteByMap(map);
}
逻辑删除
在数据库中没有被移出,而是通过一个变量来让他失效
防止数据的丢失 回收站原理
说明:
只对自动注入的 sql 起效
测试
1、在数据表中增加一个deleted字段
2、在实体类增加字段和注解(新版本不用加注解,只需要在配置文件中标注字段名)
3、添加配置(新版本不需要添加组件)
mybatis-plus:
global-config:
db-config:
logic-delete-field: deleted # 全局逻辑删除的实体字段名
logic-delete-value: 1 # 逻辑已删除值(默认为 1)
logic-not-delete-value: 0 # 逻辑未删除值(默认为 0)
4、测试
删除
查询
条件构造器
Wrapper,写一些比较复杂的sql语句时,就使用它
条件构造器 | MyBatis-Plus (baomidou.com)
自动生成代码插件
前提:设计好数据库
1、导入依赖
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-generator</artifactId>
<version>3.5.2</version>
</dependency>
2、创建一个java文件编写快速生成代码
FastAutoGenerator.create("url", "username", "password")
.globalConfig(builder -> { //全局配置
builder.author("baomidou") // 设置作者
.enableSwagger() // 开启 swagger 模式
.fileOverride() // 覆盖已生成文件
.outputDir("D://"); // 指定输出目录
})
.packageConfig(builder -> { //包配置
builder.parent("com.baomidou.mybatisplus.samples.generator") // 设置父包名
.moduleName("system") // 设置父包模块名
.pathInfo(Collections.singletonMap(OutputFile.mapperXml, "D://")); // 设置mapperXml生成路径
})
.strategyConfig(builder -> { //策略配置
builder.addInclude("t_simple") // 设置需要生成的表名
.addTablePrefix("t_", "c_"); // 设置过滤表前缀
})
.templateEngine(new FreemarkerTemplateEngine()) // 使用Freemarker引擎模板,默认的是Velocity引擎模板
.execute();
具体配置参考:https://baomidou.com/pages/981406
学习视频来源:B站Java狂神说