扩展MybatisPlus批量插入(忽略唯一索引冲突行)

更新时间:2023-05-22 08:50:31 阅读: 评论:0

扩展MybatisPlus批量插⼊(忽略唯⼀索引冲突⾏)
⼀、背景
1. 在数据同步或者幂等场景下,常常需要设置唯⼀索引来避免重复请求,lect and update效率低,且并发时还是会报错,并不友好,
那么可以⽤Mysql的Inrt ignore语法来优化。
2. MybatisPlus官⽅并没有针此处场景进⾏⽀持
⼆、环境
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-boot-starter</artifactId>
<version>3.1.0</version>
<exclusions>
<exclusion>
<groupId>com.baomidou</groupId>
韩文翻译器在线翻译<artifactId>mybatis-plus-generator</artifactId>
</exclusion>
</exclusions>
</dependency>
三、注⼊⾃定义批量插⼊sql
因为只需要改造inrtBatchSomeColumn⽅法,那直接CV就好
inrtBatchSomeColumn⽅法属于mybatis plus官⽅扩展包中
1. sql模板
import IdType;
import SqlMethod;
import AbstractMethod;
import TableFieldInfo;
import TableInfo;
import Asrt;
import StringUtils;
import TableInfoHelper;
import SqlScriptUtils;
import Jdbc3KeyGenerator;
import KeyGenerator;
import NoKeyGenerator;
import MappedStatement;
import SqlSource;
import Predicate;
/**
* @author: EnumaElish
* @Date: 2021/6/1 14:08
* @Description: 参考InrtBatchSomeColumn实现,就替换了sqlTemplate
* <p> 不同的数据库⽀持度不⼀样只在 mysql 下测试过只在 mysql 下测试过只在 mysql 下测试过 </p>
* <p> 除了主键是 <strong> 数据库⾃增的未测试 </strong> 外理论上都可以使⽤ </p>
* <p> 如果你使⽤⾃增有报错或主键值⽆法回写到entity,就不要跑来问为什么了,因为我也不知道 </p>
* <p>
* ⾃⼰的通⽤ mapper 如下使⽤:
* <pre>
* int fastSaveIgnoreBatch(List<T> entityList);
* </pre>
* </p>
*
* <li> 注意1: 不要加任何注解 !! </li>
* <li> 注意2: ⾃选字段 inrt !!,如果个别字段在 entity ⾥为 null 但是数据库中有配置默认值, inrt 后数据库字段是为 null ⽽不是默认值 </li>
* <li> 注意2: ⾃选字段 inrt !!,如果个别字段在 entity ⾥为 null 但是数据库中有配置默认值, inrt 后数据库字段是为 null ⽽不是默认值 </li>
*
* <p>
* 常⽤的构造⼊参:
* </p>
*水立方介绍
* <li> 例1: new InrtIgnoreBatchAllColumn(t -> true) , 表⽰⽤于全字段 </li>
* <li> 例2: new InrtIgnoreBatchAllColumn(t -> !t.isLogicDelete()) , 表⽰⾮逻辑删除字段外全字段 </li>
* <li> 例3: new InrtIgnoreBatchAllColumn(t -> t.getFieldFill() != FieldFill.UPDATE) , 表⽰填充策略为 UPDATE 外的全字段 </li>
*
*/
public class InrtIgnoreBatchAllColumn extends AbstractMethod {
/**
* mapper 对应的⽅法名
*/
private static final String MAPPER_METHOD ="inrtIgnoreBatchAllColumn";
private Predicate<TableFieldInfo> predicate;
public InrtIgnoreBatchAllColumn(Predicate<TableFieldInfo> predicate){
this.predicate = predicate;
}
@SuppressWarnings("Duplicates")
@Override
public MappedStatement injectMappedStatement(Class<?> mapperClass, Class<?> modelClass, TableInfo tableInfo){
KeyGenerator keyGenerator =new NoKeyGenerator();
SqlMethod sqlMethod = SqlMethod.INSERT_ONE;学习雅思
String sqlTemplate ="<script>\nINSERT IGNORE INTO %s %s VALUES %s\n</script>";
String inrtSqlColumn = SomeInrtSqlColumn(predicate);
String columnScript = LEFT_BRACKET + inrtSqlColumn.substring(0, inrtSqlColumn.length()-1)+ RIGHT_BRACKET;
String inrtSqlProperty = SomeInrtSqlProperty(ENTITY_DOT, predicate);
inrtSqlProperty = LEFT_BRACKET + inrtSqlProperty.substring(0, inrtSqlProperty.length()-1)+ RIGHT_BRACKET;
String valuesScript = vertForeach(inrtSqlProperty,"list",null, ENTITY, COMMA);
String keyProperty =null;
String keyColumn =null;
// 表包含主键处理逻辑,如果不包含主键当普通字段处理
if(StringUtils.KeyProperty())){
IdType()== IdType.AUTO){
/** ⾃增主键 */
keyGenerator =new Jdbc3KeyGenerator();
keyProperty = KeyProperty();
keyColumn = KeyColumn();
}el{
if(null!= KeySequence()){
keyGenerator = KeyGenerator(tableInfo, builderAssistant, Method(), languageDriver);
keyProperty = KeyProperty();
keyColumn = KeyColumn();
}
}
}
String sql = String.format(sqlTemplate, TableName(), columnScript, valuesScript);
SqlSource sqlSource = ateSqlSource(configuration, sql, modelClass);
return this.addInrtMappedStatement(mapperClass, modelClass, MAPPER_METHOD, sqlSource, keyGenerator, keyProperty, keyColumn); }
}
2. 注⼊sql
mport AbstractMethod;
import AbstractSqlInjector;
import Inrt;
import*;
import List;
import Stream;
import List;
/**
* @author: EnumaElish
* @Date: 2021/6/1 14:22
* @Description: LogicSqlInjector 实现上加InrtIgnoreBatchAllColumn
*/
public class CustomerSqlInjector extends AbstractSqlInjector {
@Override
public List<AbstractMethod>getMethodList(){
return Stream.of(
new Inrt(),
new LogicDelete(),
new LogicDeleteByMap(),
new LogicDeleteById(),
new LogicDeleteBatchByIds(),
办英语四级成绩单new LogicUpdate(),
new LogicUpdateById(),
new LogicSelectById(),
new LogicSelectBatchByIds(),
new LogicSelectByMap(),
new LogicSelectOne(),
new LogicSelectCount(),
new LogicSelectMaps(),
new LogicSelectMapsPage(),
new LogicSelectObjs(),
new LogicSelectList(),
new LogicSelectPage(),
// 批量新增
new InrtIgnoreBatchAllColumn(t->!t.isLogicDelete())
).collect(toList());
}
}
3. 配置DataSourceConfig,调整GlobalConfig中的tSqlInjector
@Configuration
@MapperScan(baPackages ="XXX",sqlSessionFactoryRef="sqlSessionFactory")
public class DataSourceConfig {
// 忽略DataSource
@Bean
public GlobalConfig globalConfiguration(){
GlobalConfig conf =new GlobalConfig();
conf.tBanner(true)// 是否打印
//    .tSqlInjector(new LogicSqlInjector()) // 逻辑注⼊sql
// 逻辑注⼊sql
christmas carol.tSqlInjector(new CustomerSqlInjector())
.tDbConfig(new GlobalConfig.DbConfig()
.tLogicDeleteValue("1")
.tLogicNotDeleteValue("0")
.tIdType(IdType.AUTO));// 使⽤数据库⽣成⽅式
return conf;
}
/**
* 数据源sqlSessionFactory配置
* 更多参数设置参考/config/#%E8%BF%9B%E9%98%B6%E9%85%8D%E7%BD%AE
*/
@Bean
@Primary
public SqlSessionFactory sqlSessionFactory(DataSource dataSource, PaginationInterceptor paginationInterceptor, GlobalConfig globalConfiguration)thro ws Exception {
MybatisSqlSessionFactoryBean sqlSessionFactory =new MybatisSqlSessionFactoryBean();
/* 数据源 */
sqlSessionFactory.tDataSource(dataSource);
/* 枚举扫描 */
sqlSessionFactory.tTypeEnumsPackage("xxx");
//  /* xml路径配置 */
//  sqlSessionFactory.tMapperLocations(new PathMatchingResourcePatternResolver().getResources("classpath*:mapper/*.xml"));
/* entity扫描,mybatis的Alias功能 */
sqlSessionFactory.tTypeAliasPackage("xxx");
/* entity扫描,mybatis的Alias功能 */
MybatisConfiguration configuration =new MybatisConfiguration();
configuration.tJdbcTypeForNull(JdbcType.NULL);
/* 驼峰转下划线 */
configuration.tMapUnderscoreToCamelCa(fal);加拿大留学咨询
/* 分页插件 */
configuration.addInterceptor(paginationInterceptor);
/* 允许JDBC⽀持⾃动⽣成主键 */
configuration.tUGeneratedKeys(true);
/* 乐观锁插件 */
configuration.addInterceptor(new OptimisticLockerInterceptor());
sqlSessionFactory.tConfiguration(configuration);
sqlSessionFactory.tGlobalConfig(globalConfiguration);
Object();
}
}
考研专业课试卷4. 通⽤mapper好好学习天天向上英语怎么说
public interface CommonMapper<T>extends BaMapper<T>{
/**
* 全量插⼊,等价于inrt,忽略唯⼀索引冲突的⾏
* {@link InrtIgnoreBatchAllColumn}
*
* @param entityList
* @return
*/
int inrtIgnoreBatchAllColumn(List<T> entityList);
}
5. 通⽤Service
public class CommonServiceImpl<M extends CommonMapper<T>, T>extends ServiceImpl<M, T>{
/**
* 根据业务情况调整最⼤每次批量数,mysql是有语句长度限制的,max_allow_packet是MySQL控制⽹络包⼤⼩的参数,有的版本默认1M,有的版本默认4M  */
public static final int BATCH_SIZE =500;
/**
* 加事务是参考mybatis-plus saveBatch也加,防⽌⾮数据库异常需要回滚,如果要极限性能可⾃⾏去掉,⾃⼰做补偿重试
* @param list
* @param batchSize
* @return
*/
@Transactional(rollbackFor = Exception.class)
public boolean fastSaveIgnoreBatch(List<T> list,int batchSize){
if(CollectionUtils.isEmpty(list)){
return true;
}
batchSize = batchSize <1? BATCH_SIZE : batchSize;
if(list.size()<= batchSize){
return retBool(baMapper.inrtIgnoreBatchAllColumn(list));
the magic key}
for(int fromIdx =0, endIdx = batchSize ;; fromIdx += batchSize, endIdx += batchSize){
if(endIdx > list.size()){
endIdx = list.size();
}
baMapper.inrtIgnoreBatchAllColumn(list.subList(fromIdx, endIdx));
if(endIdx == list.size()){
return true;
}
}
}
/
**
* 加事务是参考mybatis-plus saveBatch也加,防⽌⾮数据库异常需要回滚,果要极限性能可⾃⾏去掉,⾃⼰做补偿重试
好莱坞大片推荐
* @param list
* @return
*/
@Transactional(rollbackFor = Exception.class)
public boolean fastSaveIgnoreBatch(List<T> list){
return fastSaveIgnoreBatch(list, BATCH_SIZE);
}
}

本文发布于:2023-05-22 08:50:31,感谢您对本站的认可!

本文链接:https://www.wtabcd.cn/fanwen/fan/90/118125.html

版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。

标签:数据库   需要   批量   参考   字段   配置   逻辑   实现
相关文章
留言与评论(共有 0 条评论)
   
验证码:
Copyright ©2019-2022 Comsenz Inc.Powered by © 专利检索| 网站地图