mybatis-plus如何根據(jù)任意字段saveOrUpdateBatch
使用場景
mybatisplus Iservice接口下的saveOrUpdateBatch方法默認是根據(jù)主鍵來決定是要更新還是插入的,
如果要根據(jù)其他字段(必須是唯一約束,唯一約束字段可以是多個)更新的話,則需要在項目的service層重寫該方法。
方法源碼
@Transactional(
rollbackFor = {Exception.class}
)
public boolean saveOrUpdateBatch(Collection<T> entityList, int batchSize) {
TableInfo tableInfo = TableInfoHelper.getTableInfo(this.entityClass);
Assert.notNull(tableInfo, "error: can not execute. because can not find cache of TableInfo for entity!", new Object[0]);
String keyProperty = tableInfo.getKeyProperty();
Assert.notEmpty(keyProperty, "error: can not execute. because can not find column for id from entity!", new Object[0]);
return SqlHelper.saveOrUpdateBatch(this.entityClass, this.mapperClass, this.log, entityList, batchSize, (sqlSession, entity) -> {
Object idVal = ReflectionKit.getFieldValue(entity, keyProperty);
return StringUtils.checkValNull(idVal) || CollectionUtils.isEmpty(sqlSession.selectList(this.getSqlStatement(SqlMethod.SELECT_BY_ID), entity));
}, (sqlSession, entity) -> {
MapperMethod.ParamMap<T> param = new MapperMethod.ParamMap();
param.put("et", entity);
sqlSession.update(this.getSqlStatement(SqlMethod.UPDATE_BY_ID), param);
});
}
從源碼中可以看出實現(xiàn)saveOrUpdateBatch的主要方法就是SqlHelper.saveOrUpdateBatch
public static <E> boolean saveOrUpdateBatch(Class<?> entityClass, Class<?> mapper, Log log, Collection<E> list, int batchSize, BiPredicate<SqlSession, E> predicate, BiConsumer<SqlSession, E> consumer) {
String sqlStatement = getSqlStatement(mapper, SqlMethod.INSERT_ONE);
return executeBatch(entityClass, log, list, batchSize, (sqlSession, entity) -> {
if (predicate.test(sqlSession, entity)) {
sqlSession.insert(sqlStatement, entity);
} else {
consumer.accept(sqlSession, entity);
}
});
}
該方法的最后兩個參數(shù)predicate,consumer
predicate 這個函數(shù)是用于判斷是否要進行插入操作 true插入,false:則通過consumer 函數(shù)執(zhí)行更新
方法改造
注意:寫在項目操作對應表的service層
首先在service層定義接口
boolean saveOrUpdateBatchByAgentIdAndPeriodAndType(List<Entity> list);
類為數(shù)據(jù)庫表對應的實體類,agentId,period,type,這個三個字段為表的唯一約束,即當表中存在這三個字段組合對應的記錄時則進行更新操作,不存在則進行插入操作
service層接口實現(xiàn)
@Transactional(rollbackFor = Exception.class)
@DS("XXXX")//如果為多數(shù)據(jù)源,這里要指明具體操作的數(shù)據(jù)源名稱
public boolean saveOrUpdateBatchByAgentIdAndPeriodAndType(List<Entity> list) {
return SqlHelper.saveOrUpdateBatch(entityClass, this.mapperClass, super.log, list, DEFAULT_BATCH_SIZE, (sqlSession, entity) -> {//這里主要是查詢唯一約束對應的記錄是否存在
LambdaQueryWrapper<Entity> queryWrapper = Wrappers.<Entity>lambdaQuery()
.eq(Entity::getAgentId, entity.getAgentId()).eq(Entity::getPeriod,entity.getPeriod())
.eq(Entity::getType,entity.getType());
Map<String, Object> map = CollectionUtils.newHashMapWithExpectedSize(1);
map.put(Constants.WRAPPER, queryWrapper);
return CollectionUtils.isEmpty(sqlSession.selectList(getSqlStatement(SqlMethod.SELECT_LIST), map));
}, (sqlSession, entity) -> {
LambdaUpdateWrapper<Entity> lambdaUpdateWrapper = new LambdaUpdateWrapper<>();
lambdaUpdateWrapper.eq(Entity::getAgentId, entity.getAgentId()).eq(Entity::getPeriod,entity.getPeriod())
.eq(Entity::getType,entity.getType());
Map<String, Object> param = CollectionUtils.newHashMapWithExpectedSize(2);
param.put(Constants.ENTITY, entity);
param.put(Constants.WRAPPER, lambdaUpdateWrapper);
sqlSession.update(getSqlStatement(SqlMethod.UPDATE), param);
});
}
非批量的saveOrUpdate也可以按照這種方式進行改造
總結
以上為個人經驗,希望能給大家一個參考,也希望大家多多支持腳本之家。
相關文章
java實現(xiàn)上傳網(wǎng)絡圖片到微信臨時素材
這篇文章主要為大家詳細介紹了java實現(xiàn)上傳網(wǎng)絡圖片到微信臨時素材,網(wǎng)絡圖片上傳到微信服務器,具有一定的參考價值,感興趣的小伙伴們可以參考一下2018-07-07
Java?Springboot異步執(zhí)行事件監(jiān)聽和處理實例
Java?SpringBoot中,監(jiān)聽和處理事件是一種常見的模式,它允許不同的組件之間通過事件進行通信,事件監(jiān)聽和處理通常通過Spring的事件發(fā)布-訂閱模型來實現(xiàn),一個簡單的Spring?Boot應用程序示例,其中將包括事件的定義、事件的發(fā)布以及事件的監(jiān)聽2024-07-07
線程池之newFixedThreadPool定長線程池的實例
這篇文章主要介紹了線程池之newFixedThreadPool定長線程池的實例,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教2021-06-06
IntelliJ IDEA2020.2.2創(chuàng)建Servlet方法及404問題
這篇文章主要介紹了IntelliJ IDEA2020.2.2創(chuàng)建Servlet方法及404問題,這里小編使用的2020.2.2企業(yè)破解版本,本文通過圖文并茂的形式給大家介紹的非常詳細,對大家的學習或工作具有一定的參考借鑒價值,需要的朋友可以參考下2020-09-09

