|
@@ -26,16 +26,10 @@ import com.baomidou.mybatisplus.extension.toolkit.SqlHelper;
|
|
|
import org.apache.ibatis.binding.MapperMethod;
|
|
|
import org.apache.ibatis.logging.Log;
|
|
|
import org.apache.ibatis.logging.LogFactory;
|
|
|
-import org.apache.ibatis.reflection.ExceptionUtil;
|
|
|
-import org.apache.ibatis.session.ExecutorType;
|
|
|
import org.apache.ibatis.session.SqlSession;
|
|
|
-import org.apache.ibatis.session.SqlSessionFactory;
|
|
|
-import org.mybatis.spring.MyBatisExceptionTranslator;
|
|
|
-import org.mybatis.spring.SqlSessionHolder;
|
|
|
import org.mybatis.spring.SqlSessionUtils;
|
|
|
import org.springframework.beans.factory.annotation.Autowired;
|
|
|
import org.springframework.transaction.annotation.Transactional;
|
|
|
-import org.springframework.transaction.support.TransactionSynchronizationManager;
|
|
|
|
|
|
import java.io.Serializable;
|
|
|
import java.util.Collection;
|
|
@@ -44,6 +38,8 @@ import java.util.Objects;
|
|
|
import java.util.function.BiConsumer;
|
|
|
import java.util.function.Consumer;
|
|
|
import java.util.function.Function;
|
|
|
+import java.util.function.Predicate;
|
|
|
+import java.util.function.Supplier;
|
|
|
|
|
|
/**
|
|
|
* IService 实现类( 泛型:M 是 mapper 对象,T 是实体 )
|
|
@@ -155,15 +151,13 @@ public class ServiceImpl<M extends BaseMapper<T>, T> implements IService<T> {
|
|
|
Assert.notNull(tableInfo, "error: can not execute. because can not find cache of TableInfo for entity!");
|
|
|
String keyProperty = tableInfo.getKeyProperty();
|
|
|
Assert.notEmpty(keyProperty, "error: can not execute. because can not find column for id from entity!");
|
|
|
- return executeBatch(entityList, batchSize, (sqlSession, entity) -> {
|
|
|
+ return SqlHelper.saveOrUpdateBatch(this.entityClass, this.log, entityList, batchSize, entity -> {
|
|
|
Object idVal = ReflectionKit.getFieldValue(entity, keyProperty);
|
|
|
- if (StringUtils.checkValNull(idVal) || Objects.isNull(getById((Serializable) idVal))) {
|
|
|
- sqlSession.insert(tableInfo.getSqlStatement(SqlMethod.INSERT_ONE.getMethod()), entity);
|
|
|
- } else {
|
|
|
- MapperMethod.ParamMap<T> param = new MapperMethod.ParamMap<>();
|
|
|
- param.put(Constants.ENTITY, entity);
|
|
|
- sqlSession.update(tableInfo.getSqlStatement(SqlMethod.UPDATE_BY_ID.getMethod()), param);
|
|
|
- }
|
|
|
+ return StringUtils.checkValNull(idVal) || Objects.isNull(getById((Serializable) idVal));
|
|
|
+ }, (sqlSession, entity) -> {
|
|
|
+ MapperMethod.ParamMap<T> param = new MapperMethod.ParamMap<>();
|
|
|
+ param.put(Constants.ENTITY, entity);
|
|
|
+ sqlSession.update(tableInfo.getSqlStatement(SqlMethod.UPDATE_BY_ID.getMethod()), param);
|
|
|
});
|
|
|
}
|
|
|
|
|
@@ -205,36 +199,7 @@ public class ServiceImpl<M extends BaseMapper<T>, T> implements IService<T> {
|
|
|
*/
|
|
|
@Deprecated
|
|
|
protected boolean executeBatch(Consumer<SqlSession> consumer) {
|
|
|
- SqlSessionFactory sqlSessionFactory = SqlHelper.sqlSessionFactory(entityClass);
|
|
|
- SqlSessionHolder sqlSessionHolder = (SqlSessionHolder) TransactionSynchronizationManager.getResource(sqlSessionFactory);
|
|
|
- boolean transaction = TransactionSynchronizationManager.isSynchronizationActive();
|
|
|
- if (sqlSessionHolder != null) {
|
|
|
- SqlSession sqlSession = sqlSessionHolder.getSqlSession();
|
|
|
- //原生无法支持执行器切换,当存在批量操作时,会嵌套两个session的,优先commit上一个session
|
|
|
- //按道理来说,这里的值应该一直为false。
|
|
|
- sqlSession.commit(!transaction);
|
|
|
- }
|
|
|
- SqlSession sqlSession = sqlSessionFactory.openSession(ExecutorType.BATCH);
|
|
|
- if (!transaction) {
|
|
|
- log.warn("SqlSession [" + sqlSession + "] was not registered for synchronization because DataSource is not transactional");
|
|
|
- }
|
|
|
- try {
|
|
|
- consumer.accept(sqlSession);
|
|
|
- //非事物情况下,强制commit。
|
|
|
- sqlSession.commit(!transaction);
|
|
|
- return true;
|
|
|
- } catch (Throwable t) {
|
|
|
- sqlSession.rollback();
|
|
|
- Throwable unwrapped = ExceptionUtil.unwrapThrowable(t);
|
|
|
- if (unwrapped instanceof RuntimeException) {
|
|
|
- MyBatisExceptionTranslator myBatisExceptionTranslator
|
|
|
- = new MyBatisExceptionTranslator(sqlSessionFactory.getConfiguration().getEnvironment().getDataSource(), true);
|
|
|
- throw Objects.requireNonNull(myBatisExceptionTranslator.translateExceptionIfPossible((RuntimeException) unwrapped));
|
|
|
- }
|
|
|
- throw ExceptionUtils.mpe(unwrapped);
|
|
|
- } finally {
|
|
|
- sqlSession.close();
|
|
|
- }
|
|
|
+ return SqlHelper.executeBatch(this.entityClass, this.log, consumer);
|
|
|
}
|
|
|
|
|
|
/**
|
|
@@ -248,18 +213,7 @@ public class ServiceImpl<M extends BaseMapper<T>, T> implements IService<T> {
|
|
|
* @since 3.3.1
|
|
|
*/
|
|
|
protected <E> boolean executeBatch(Collection<E> list, int batchSize, BiConsumer<SqlSession, E> consumer) {
|
|
|
- Assert.isFalse(batchSize < 1, "batchSize must not be less than one");
|
|
|
- return !CollectionUtils.isEmpty(list) && executeBatch(sqlSession -> {
|
|
|
- int size = list.size();
|
|
|
- int i = 1;
|
|
|
- for (E element : list) {
|
|
|
- consumer.accept(sqlSession, element);
|
|
|
- if ((i % batchSize == 0) || i == size) {
|
|
|
- sqlSession.flushStatements();
|
|
|
- }
|
|
|
- i++;
|
|
|
- }
|
|
|
- });
|
|
|
+ return SqlHelper.executeBatch(this.entityClass, this.log, list, batchSize, consumer);
|
|
|
}
|
|
|
|
|
|
/**
|
|
@@ -274,4 +228,38 @@ public class ServiceImpl<M extends BaseMapper<T>, T> implements IService<T> {
|
|
|
protected <E> boolean executeBatch(Collection<E> list, BiConsumer<SqlSession, E> consumer) {
|
|
|
return executeBatch(list, DEFAULT_BATCH_SIZE, consumer);
|
|
|
}
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 批量更新或新增
|
|
|
+ *
|
|
|
+ * @param list 数据集合
|
|
|
+ * @param batchSize 批量大小
|
|
|
+ * @param predicate 新增条件 notnull
|
|
|
+ * @param function 更新条件 notnull
|
|
|
+ * @return 操作结果
|
|
|
+ * @since 3.3.3
|
|
|
+ */
|
|
|
+ protected boolean saveOrUpdateBatch(Collection<T> list, int batchSize, Predicate<T> predicate, Function<T, Wrapper<T>> function) {
|
|
|
+ TableInfo tableInfo = TableInfoHelper.getTableInfo(entityClass);
|
|
|
+ return SqlHelper.saveOrUpdateBatch(this.entityClass, this.log, list, batchSize, predicate, ((sqlSession, entity) -> {
|
|
|
+ String sqlStatement = tableInfo.getSqlStatement(SqlMethod.UPDATE.getMethod());
|
|
|
+ MapperMethod.ParamMap<Object> param = new MapperMethod.ParamMap<>();
|
|
|
+ param.put(Constants.ENTITY, entity);
|
|
|
+ param.put(Constants.WRAPPER, function.apply(entity));
|
|
|
+ sqlSession.update(sqlStatement, param);
|
|
|
+ }));
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 批量更新或新增
|
|
|
+ *
|
|
|
+ * @param list 数据集合
|
|
|
+ * @param predicate 新增条件
|
|
|
+ * @param updateFunction 更新条件
|
|
|
+ * @return 操作结果
|
|
|
+ * @since 3.3.3
|
|
|
+ */
|
|
|
+ protected boolean saveOrUpdateBatch(Collection<T> list, Predicate<T> predicate, Function<T,Wrapper<T>> updateFunction) {
|
|
|
+ return saveOrUpdateBatch(list, DEFAULT_BATCH_SIZE, predicate, updateFunction);
|
|
|
+ }
|
|
|
}
|