首先完成MyBatis-Plus基础整合。可以参考上一篇文章SpringBoot整合MyBatis-Plus
需要自动填充的字段添加属性
@Data
@TableName("salesbill")
public class Salesbill {
@TableId(value = "billId",type = IdType.AUTO)
private long billId;
@JsonFormat(pattern = "yyyy-MM-dd")
private Date date;
@TableField("customerID")
private long customerID;
@TableField("categoryID")
private long categoryID;
private double price;
private double grossWeight;
private double tareWeight;
private String remack;
private long address;
// 注意!这里需要标记为填充字段
@TableField(fill = FieldFill.INSERT)
private String createName;
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
// 注意!这里需要标记为填充字段
@TableField(fill = FieldFill.INSERT)
private Date createTime;
}
@Slf4j
@Component
public class MyMetaObjectHandler implements MetaObjectHandler {
@Override
public void insertFill(MetaObject metaObject) {
log.info("start insert fill ....");
this.strictInsertFill(metaObject, "createTime", LocalDateTime::now, LocalDateTime.class);
this.strictInsertFill(metaObject, "createName", ()->"fgrapp", String.class);
}
@Override
public void updateFill(MetaObject metaObject) {
log.info("start update fill ....");
this.strictUpdateFill(metaObject, "createName", ()->"fgrapp", String.class);
this.strictUpdateFill(metaObject, "createTime", LocalDateTime::now, LocalDateTime.class);
}
}
POST /Salesbill HTTP/1.1
Host: localhost:8000
Content-Type: application/json
Cache-Control: no-cache
Postman-Token: 3a10c096-052c-0ae5-7c44-08018aa14f00
{
"date": "2020-11-21",
"customerID": 2,
"categoryID": 2,
"price": 2,
"grossWeight": 10,
"tareWeight": 2,
"remack": "测试",
"address": 1
}
{
"billId": 24,
"date": "2020-11-21",
"customerID": 2,
"categoryID": 2,
"price": 2,
"grossWeight": 10,
"tareWeight": 2,
"remack": "测试",
"address": 1,
"createName": "fgrapp",
"createTime": "2021-09-06 10:32:55"
}
根据返回结果可以看到,createName,createTime两个字段在没有传值的情况下填充了值
MyBatis-Plus默认是没有提供批量新增的方法,我们可以通过SQL注入的方式添加批量新增的方法。
public class InsertBatch extends AbstractMethod {
@Override
public MappedStatement injectMappedStatement(Class<?> mapperClass, Class<?> modelClass, TableInfo tableInfo) {
final String sql = "";
final String fieldSql = prepareFieldSql(tableInfo);
final String valueSql = prepareValuesSqlForMysqlBatch(tableInfo);
final String sqlResult = String.format(sql, tableInfo.getTableName(), fieldSql, valueSql);
SqlSource sqlSource = languageDriver.createSqlSource(configuration, sqlResult, modelClass);
return this.addInsertMappedStatement(mapperClass, modelClass, "insertBatch", sqlSource, new NoKeyGenerator(), null, null);
}
private String prepareFieldSql(TableInfo tableInfo) {
StringBuilder fieldSql = new StringBuilder();
tableInfo.getFieldList().forEach(x -> fieldSql.append(x.getColumn()).append(","));
fieldSql.delete(fieldSql.length() - 1, fieldSql.length());
fieldSql.insert(0, "(");
fieldSql.append(")");
return fieldSql.toString();
}
private String prepareValuesSqlForMysqlBatch(TableInfo tableInfo) {
final StringBuilder valueSql = new StringBuilder();
valueSql.append("" );
tableInfo.getFieldList().forEach(x -> valueSql.append("#{item.").append(x.getProperty()).append("},"));
valueSql.delete(valueSql.length() - 1, valueSql.length());
valueSql.append("");
return valueSql.toString();
}
}
public class MyLogicSqlInjector extends DefaultSqlInjector {
/**
* 如果只需增加方法,保留MP自带方法
* 可以super.getMethodList() 再add
* @return
*/
@Override
public List<AbstractMethod> getMethodList(Class<?> mapperClass) {
List<AbstractMethod> methodList = super.getMethodList(mapperClass);
methodList.add(new InsertBatch());
return methodList;
}
}
@Configuration
@MapperScan("com.fgrapp.learn.dao")
public class MybatisPlusConfig {
/**
* 新的分页插件,一缓和二缓遵循mybatis的规则,需要设置 MybatisConfiguration#useDeprecatedExecutor = false
* 避免缓存出现问题(该属性会在旧插件移除后一同移除)
*/
@Bean
public MybatisPlusInterceptor mybatisPlusInterceptor() {
MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();
interceptor.addInnerInterceptor(new PaginationInnerInterceptor(DbType.MYSQL));
return interceptor;
}
@Bean
public ConfigurationCustomizer configurationCustomizer() {
return configuration -> configuration.setUseDeprecatedExecutor(false);
}
/**
* 自定义 SqlInjector
* 里面包含自定义的全局方法
*/
@Bean
public MyLogicSqlInjector myLogicSqlInjector() {
return new MyLogicSqlInjector();
}
}
/**
* 批量插入
* @param batchList 插入列表
* @return 插入数量
*/
int insertBatch(@Param("list") List<Salesbill> batchList);
public void insertBatch(List<Salesbill> list){
baseMapper.insertBatch(list);
}
@PostMapping("batch")
public void insertBatch(@RequestBody List<Salesbill> list){
service.insertBatch(list);
}
POST /Salesbill/batch HTTP/1.1
Host: localhost:8000
Content-Type: application/json
Cache-Control: no-cache
Postman-Token: 552371ff-3342-1aa3-37e9-19f585f7b318
[
{
"date": "2020-11-21",
"customerID": 2,
"categoryID": 2,
"price": 2,
"grossWeight": 10,
"tareWeight": 2,
"remack": "测试",
"address": 1
},
{
"date": "2020-11-21",
"customerID": 2,
"categoryID": 2,
"price": 2,
"grossWeight": 10,
"tareWeight": 2,
"remack": "测试",
"address": 1
}
]
我这里为了方便就把批量插入的方法直接写在了具体的Mapper接口内,这样的话,在多个业务类需要批量插入的情况下,就需要在多处添加批量插入的方法。
更进一步的方式可以选择定义一个项目内所有Mapper接口的父接口。如下所示:
public interface FgrMapper<T> extends BaseMapper<T> {
/**
* 批量插入
* @param batchList 插入列表
* @return 插入数量
*/
int insertBatch(@Param("list") List<T> batchList);
}
这样的话,具体的业务类就继承这个接口,这样就可以令项目中所有Mapper接口都包含批量插入的方法。
public interface FileMapper extends FgrMapper<FileResponse> {
}