美文网首页程序员
代码版insertOnDuplicateKeyUpdate

代码版insertOnDuplicateKeyUpdate

作者: geekerzhou | 来源:发表于2022-10-24 19:56 被阅读0次

    并发插入数据导致数据库唯一键冲突报DuplicateKeyException,可以使用replace into,insert on duplicate key update来解决,但是会有mysql锁的问题,用代码来解决

    public abstract class DbUtils {
    
        private static final Logger LOGGER = LoggerFactory.getLogger(DbUtils.class);
    
        public static  <T, KEY> int insertOnDuplicateKeyUpdate(List<T> dataList, Function<T, KEY> getUniqueKey,
                Function<List<T>, Integer> doInsert, Function<List<T>, List<T>> queryExists,
                BiFunction<List<T>, List<T>, Integer> doUpdate, int tryCount) {
    
            Object savePoint = null;
            try {
                savePoint = TransactionSynchronizationManager.isActualTransactionActive() ? TransactionAspectSupport.currentTransactionStatus().createSavepoint() : null;
    
                Integer result = doInsert.apply(dataList);
                return result;
            }
            catch (DuplicateKeyException onDuplicate) {
                if (tryCount == 0) {
                    throw onDuplicate;
                }
                if (savePoint != null) {
                    TransactionAspectSupport.currentTransactionStatus().rollbackToSavepoint(savePoint);
                }
    
                List<T> existsList = queryExists.apply(dataList);
                Set<KEY> existsKeys = existsList.stream().map(getUniqueKey).collect(Collectors.toSet());
                List<T> insertList = dataList.stream().filter(x -> !existsKeys.contains(getUniqueKey.apply(x))).collect(Collectors.toList());
                List<T> updateList = dataList.stream().filter(x -> existsKeys.contains(getUniqueKey.apply(x))).collect(Collectors.toList());
    
                int updateResult = doUpdate.apply(existsList, updateList);
                int insertResult = CollectionUtils.isNotEmpty(insertList) ? insertOnDuplicateKeyUpdate(insertList, getUniqueKey, doInsert, queryExists, doUpdate, tryCount - 1) : 0;
                LOGGER.info("onDuplicateKey insert size {} result {}, update size {} result {} {}",
                        insertList.size(), insertResult, updateList.size(), updateResult, savePoint == null? "": "transactional");
    
                return insertResult + updateResult;
            }
        }
    }
    

    相关文章

      网友评论

        本文标题:代码版insertOnDuplicateKeyUpdate

        本文链接:https://www.haomeiwen.com/subject/wuigzrtx.html