MyBatisPlus体验及使用

MyBatis 的增强版,但是我现在用的不多,JPA 为主

一、快速使用

  • 1、编写 pojo
1
2
3
4
5
6
7
8
9
@Data
@AllArgsConstructor
@NoArgsConstructor
public class User {
private Long id;
private String name;
private Integer age;
private String email;
}
  • 2、SpringBoot 添加扫描包
1
2
3
4
5
6
7
@SpringBootApplication
@MapperScan("com.lqs.mybatisplusstart.mapper") //扫描mapper文件夹
public class MybatisplusstartApplication {
public static void main(String[] args) {
SpringApplication.run(MybatisplusstartApplication.class, args);
}
}
  • 3、编写 mapper 接口
1
2
3
4
5
6
/**
* 继承基本的BaseMapper
* 传入泛型
*/
public interface UserMapper extends BaseMapper<User> {
}

二、配置日志

1
2
3
mybatis-plus:
configuration:
log-impl: org.apache.ibatis.logging.stdout.StdOutImpl

三、CRUD 扩展

1、自动填充

创建时间,修改时间,一般自动化完成

  • alibaba 开发手册:gmt_created, gmt_modified 都必须有,需要自动
1
2
3
4
@TableField(fill = FieldFill.INSERT)
private LocalDateTime gmtCreated;
@TableField(fill = FieldFill.INSERT_UPDATE)
private LocalDateTime gmtModified;

编写处理器

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
@Slf4j
@Component
public class MyMetaObjectHandler implements MetaObjectHandler {
//插入的更新策略
@Override
public void insertFill(MetaObject metaObject) {
Log.info("start insert fill...");
//String fieldName, Object fieldVal, MetaObject metaObject
this.setFieldValByName("gmtCreated", LocalDateTime.now(), metaObject);
}
//更新的策略
@Override
public void updateFill(MetaObject metaObject) {
Log.info("start insert update fill...");
this.setFieldValByName("gmtModified", LocalDateTime.now(), metaObject);
}
}

2、乐/悲观锁

乐观锁:认为不会出现问题,做什么都不加锁。出现问题之后再次更新值测试

悲观锁:认为会出现问题,干什么都上锁,再去操作

实体类增加对应的字段

1
2
@Version //乐观锁注解
private Integer version;

注册组件

1
2
3
4
5
6
7
8
9
10
@EnableTransactionManagement
//扫描mapper文件夹,将主类的配置拿到此处
@MapperScan("com.lqs.mybatisplusstart.mapper")
@Configuration
public class MybatisPlusConfig {
@Bean //注册乐观锁插件
public OptimisticLockerInterceptor optimisticLockerInterceptor(){
return new OptimisticLockerInterceptor();
}
}

3、逻辑删除

  • 例子:管理员可以查看被删除的东西,普通用户不可以,增加 deleted 字段
  • 增加配置
1
2
3
4
@Bean
public ISqlInjector sqlInjector(){
return new LogicSqlInjector();
}
1
2
3
4
5
6
mybatis-plus:
global-config:
db-config:
#逻辑删除
logic-delete-value: 1
logic-not-delete-value: 0

4、批量插入/批量插入或更新

  • 批量插入或更新插件
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.core.injector.AbstractMethod;
import com.baomidou.mybatisplus.core.metadata.TableFieldInfo;
import com.baomidou.mybatisplus.core.metadata.TableInfo;
import com.baomidou.mybatisplus.core.metadata.TableInfoHelper;
import com.baomidou.mybatisplus.core.toolkit.sql.SqlInjectionUtils;
import com.baomidou.mybatisplus.core.toolkit.sql.SqlScriptUtils;
import lombok.Setter;
import lombok.experimental.Accessors;
import org.apache.ibatis.executor.keygen.Jdbc3KeyGenerator;
import org.apache.ibatis.executor.keygen.KeyGenerator;
import org.apache.ibatis.executor.keygen.NoKeyGenerator;
import org.apache.ibatis.mapping.MappedStatement;
import org.apache.ibatis.mapping.SqlSource;

import java.util.List;
import java.util.function.Predicate;

/**
* <p>
* 批量插入或更新
* </p>
* @since 3.5.0
* @author aries
*/
@Setter
public class InsertOrUpdateBatch extends AbstractMethod {
private static final String NAME = "insertOrUpdateBatch";
/**
* 字段筛选条件
*/
@Accessors(chain = true)
private Predicate<TableFieldInfo> predicate;

/**
* 默认方法名
*/
public InsertOrUpdateBatch() {
super(NAME);
}

/**
* 默认方法名
*
* @param predicate 字段筛选条件
*/
public InsertOrUpdateBatch(Predicate<TableFieldInfo> predicate) {
super(NAME);
this.predicate = predicate;
}

/**
* @param name 方法名
* @param predicate 字段筛选条件
* @since 3.5.0
*/
public InsertOrUpdateBatch(String name, Predicate<TableFieldInfo> predicate) {
super(name);
this.predicate = predicate;
}

@SuppressWarnings("Duplicates")
@Override
public MappedStatement injectMappedStatement(Class<?> mapperClass, Class<?> modelClass, TableInfo tableInfo) {
KeyGenerator keyGenerator = NoKeyGenerator.INSTANCE;
String methodSql = """
<script>
INSERT INTO %s %s VALUES %s ON DUPLICATE KEY UPDATE %s
</script>""";
List<TableFieldInfo> fieldList = tableInfo.getFieldList();
String insertSqlColumn = tableInfo.getKeyInsertSqlColumn(true, null, false) +
this.filterTableFieldInfo(fieldList, predicate, TableFieldInfo::getInsertSqlColumn, EMPTY);
String columnScript = LEFT_BRACKET + insertSqlColumn.substring(0, insertSqlColumn.length() - 1) + RIGHT_BRACKET;
String insertSqlProperty = tableInfo.getKeyInsertSqlProperty(true, ENTITY_DOT, false) +
this.filterTableFieldInfo(fieldList, predicate, i -> i.getInsertSqlProperty(ENTITY_DOT), EMPTY);
String valueUpdateScript = this.filterTableFieldInfo(fieldList, predicate, f -> {
String s = f.getInsertSqlColumn().replace(",", "");
return String.format("%s =values(%s)", s, s);
}, ",");
insertSqlProperty = LEFT_BRACKET + insertSqlProperty.substring(0, insertSqlProperty.length() - 1) + RIGHT_BRACKET;
String valuesScript = SqlScriptUtils.convertForeach(insertSqlProperty, "list", null, ENTITY, COMMA);
String keyProperty = null;
String keyColumn = null;
// 表包含主键处理逻辑,如果不包含主键当普通字段处理
if (tableInfo.havePK()) {
if (tableInfo.getIdType() == IdType.AUTO) {
/* 自增主键 */
keyGenerator = Jdbc3KeyGenerator.INSTANCE;
keyProperty = tableInfo.getKeyProperty();
// 去除转义符
keyColumn = SqlInjectionUtils.removeEscapeCharacter(tableInfo.getKeyColumn());
} else {
if (null != tableInfo.getKeySequence()) {
keyGenerator = TableInfoHelper.genKeyGenerator(this.methodName, tableInfo, builderAssistant);
keyProperty = tableInfo.getKeyProperty();
keyColumn = tableInfo.getKeyColumn();
}
}
}
String sql = String.format(methodSql, tableInfo.getTableName(), columnScript, valuesScript,valueUpdateScript);
SqlSource sqlSource = super.createSqlSource(configuration, sql, modelClass);
return this.addInsertMappedStatement(mapperClass, modelClass, methodName, sqlSource, keyGenerator, keyProperty, keyColumn);
}
}
  • 添加并注入 injector
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
import com.baomidou.mybatisplus.annotation.FieldFill;
import com.baomidou.mybatisplus.core.injector.AbstractMethod;
import com.baomidou.mybatisplus.core.injector.DefaultSqlInjector;
import com.baomidou.mybatisplus.core.metadata.TableInfo;
import com.baomidou.mybatisplus.extension.injector.methods.InsertBatchSomeColumn;

import java.util.List;

public class MySqlInjector extends DefaultSqlInjector {

@Override
public List<AbstractMethod> getMethodList(Class<?> mapperClass, TableInfo tableInfo) {
List<AbstractMethod> methodList = super.getMethodList(mapperClass, tableInfo);
//这是mybatisplus自带的批量插入方法
methodList.add(new InsertBatchSomeColumn(i -> i.getFieldFill() != FieldFill.UPDATE));
methodList.add(new InsertOrUpdateBatch());
return methodList;
}
}

@Bean
public MySqlInjector sqlInjector() {
return new MySqlInjector();
}

MyBatisPlus体验及使用
https://polarisink.github.io/20220813/yuque/MyBatisPlus体验及使用/
作者
Areis
发布于
2022年8月13日
许可协议