Răsfoiți Sursa

add 新增 saveOrUpdateAll 方法 可完美替代 saveOrUpdateBatch 高性能

疯狂的狮子li 3 ani în urmă
părinte
comite
7c6fe5f244

+ 2 - 0
ruoyi-common/src/main/java/com/ruoyi/common/core/mybatisplus/core/IServicePlus.java

@@ -168,5 +168,7 @@ public interface IServicePlus<T, K> extends IService<T> {
 	}
 
 	boolean saveAll(Collection<T> entityList);
+
+	boolean saveOrUpdateAll(Collection<T> entityList);
 }
 

+ 31 - 24
ruoyi-common/src/main/java/com/ruoyi/common/core/mybatisplus/core/ServicePlusImpl.java

@@ -1,20 +1,21 @@
 package com.ruoyi.common.core.mybatisplus.core;
 
 import cn.hutool.core.bean.copier.CopyOptions;
-import com.baomidou.mybatisplus.annotation.TableId;
-import com.baomidou.mybatisplus.annotation.TableName;
+import cn.hutool.core.util.ObjectUtil;
 import com.baomidou.mybatisplus.core.conditions.Wrapper;
+import com.baomidou.mybatisplus.core.metadata.TableInfo;
+import com.baomidou.mybatisplus.core.metadata.TableInfoHelper;
+import com.baomidou.mybatisplus.core.toolkit.Assert;
 import com.baomidou.mybatisplus.core.toolkit.ClassUtils;
 import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
 import com.ruoyi.common.core.page.PagePlus;
 import com.ruoyi.common.utils.BeanCopyUtils;
+import com.ruoyi.common.utils.reflect.ReflectUtils;
 import lombok.extern.slf4j.Slf4j;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.core.ResolvableType;
 
 import java.io.Serializable;
-import java.lang.annotation.Annotation;
-import java.lang.reflect.Field;
 import java.util.ArrayList;
 import java.util.Collection;
 import java.util.List;
@@ -119,31 +120,37 @@ public class ServicePlusImpl<M extends BaseMapperPlus<T>, T, K> extends ServiceI
 
 	/**
 	 * 单sql批量插入( 全量填充 )
-	 * 适用于无脑插入
 	 */
 	@Override
 	public boolean saveAll(Collection<T> entityList) {
-		ArrayList<T> list = new ArrayList<>();
-		for (T t : entityList) {
-			try {
-				//获取属性注解的value值
-				Field f = t.getClass().getDeclaredField("id");
-				f.setAccessible( true );//设置可以范围private
-				Object o = f.get(t);//获取出id的值
-				System.out.println(o);
-				if (o == null) {
-					//如果id为null,插入
-					list.add(t);
-				} else {
-					//否则更新
-					baseMapper.updateById(t);
-				}
-
-			} catch (Exception e) {
-				e.printStackTrace();
+		return baseMapper.insertAll(entityList) == entityList.size();
+	}
+
+	/**
+	 * 全量保存或更新 ( 按主键区分 )
+	 */
+	@Override
+	public boolean saveOrUpdateAll(Collection<T> entityList) {
+		TableInfo tableInfo = TableInfoHelper.getTableInfo(entityClass);
+		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!");
+		List<T> addList = new ArrayList<>();
+		List<T> updateList = new ArrayList<>();
+		int row = 0;
+		for (T entity : entityList) {
+			Object id = ReflectUtils.invokeGetter(entity, keyProperty);
+			if (ObjectUtil.isNull(id)) {
+				addList.add(entity);
+			} else {
+				updateList.add(entity);
 			}
 		}
-		return baseMapper.insertAll(list) == list.size();
+		if (updateBatchById(updateList)) {
+			row += updateList.size();
+		}
+		row += baseMapper.insertAll(addList);
+		return row == entityList.size();
 	}
 
 	/**

+ 24 - 7
ruoyi-demo/src/main/java/com/ruoyi/demo/controller/TestBatchController.java

@@ -35,21 +35,38 @@ public class TestBatchController extends BaseController {
      * 新增批量方法 可完美替代 saveBatch 秒级插入上万数据 (对mysql负荷较大)
      */
 	@ApiOperation(value = "新增批量方法")
-    @PostMapping()
+    @PostMapping("/add")
 //	@DataSource(DataSourceType.SLAVE)
     public AjaxResult<Void> add() {
 		List<TestDemo> list = new ArrayList<>();
 		for (int i = 0; i < 10; i++) {
-			TestDemo testDemo = new TestDemo();
-			if (i % 2 == 0) {
-				list.add(testDemo.setId((long) i + 1).setTestKey("批量更新").setValue("批量更新"));
-			} else {
-				list.add(testDemo.setOrderNum(-1L).setTestKey("批量新增").setValue("测试新增"));
-			}
+			list.add(new TestDemo().setOrderNum(-1L).setTestKey("批量新增").setValue("测试新增"));
 		}
         return toAjax(iTestDemoService.saveAll(list) ? 1 : 0);
     }
 
+	/**
+	 * 新增或更新 可完美替代 saveOrUpdateBatch 高性能
+	 */
+	@ApiOperation(value = "新增或更新批量方法")
+	@PostMapping("/addOrUpdate")
+//	@DataSource(DataSourceType.SLAVE)
+	public AjaxResult<Void> addOrUpdate() {
+		List<TestDemo> list = new ArrayList<>();
+		for (int i = 0; i < 1000; i++) {
+			list.add(new TestDemo().setOrderNum(-1L).setTestKey("批量新增").setValue("测试新增"));
+		}
+		iTestDemoService.saveAll(list);
+		for (int i = 0; i < list.size(); i++) {
+			TestDemo testDemo = list.get(i);
+			testDemo.setTestKey("批量新增或修改").setValue("批量新增或修改");
+			if (i % 2 == 0) {
+				testDemo.setId(null);
+			}
+		}
+		return toAjax(iTestDemoService.saveOrUpdateAll(list) ? 1 : 0);
+	}
+
     /**
      * 删除批量方法
      */