diff --git a/backend/src/main/java/io/metersphere/base/mapper/ext/ExtCustomFieldResourceMapper.java b/backend/src/main/java/io/metersphere/base/mapper/ext/ExtCustomFieldResourceMapper.java index 9d2b075dee..ebf32cab53 100644 --- a/backend/src/main/java/io/metersphere/base/mapper/ext/ExtCustomFieldResourceMapper.java +++ b/backend/src/main/java/io/metersphere/base/mapper/ext/ExtCustomFieldResourceMapper.java @@ -1,6 +1,7 @@ package io.metersphere.base.mapper.ext; import io.metersphere.base.domain.ext.CustomFieldResource; +import io.metersphere.dto.CustomFieldResourceDTO; import org.apache.ibatis.annotations.Param; import java.util.List; @@ -20,4 +21,8 @@ public interface ExtCustomFieldResourceMapper { List getByResourceIds(@Param("tableName") String tableName, @Param("resourceIds") List resourceIds); long countFieldResource(@Param("tableName") String tableName, @Param("resourceId") String resourceId, @Param("fieldId") String field_id); + + int batchUpdateByResourceIds(@Param("tableName") String tableName, @Param("resourceIds") List resourceIds, @Param("record") CustomFieldResourceDTO customField); + + void batchInsertIfNotExists(@Param("tableName") String tableName, @Param("record") CustomFieldResourceDTO customField); } diff --git a/backend/src/main/java/io/metersphere/base/mapper/ext/ExtCustomFieldResourceMapper.xml b/backend/src/main/java/io/metersphere/base/mapper/ext/ExtCustomFieldResourceMapper.xml index b75de2e16c..0d7652aa48 100644 --- a/backend/src/main/java/io/metersphere/base/mapper/ext/ExtCustomFieldResourceMapper.xml +++ b/backend/src/main/java/io/metersphere/base/mapper/ext/ExtCustomFieldResourceMapper.xml @@ -10,6 +10,12 @@ update ${tableName} + + where resource_id = #{record.resourceId,jdbcType=VARCHAR} + and field_id = #{record.fieldId,jdbcType=VARCHAR} + + + `value` = #{record.value,jdbcType=VARCHAR}, @@ -18,8 +24,28 @@ text_value = #{record.textValue,jdbcType=LONGVARCHAR}, - where resource_id = #{record.resourceId,jdbcType=VARCHAR} - and field_id = #{record.fieldId,jdbcType=VARCHAR} + + + update ${tableName} + + where resource_id in + + #{resourceId} + + + + INSERT INTO ${tableName} (resource_id, field_id, `value`, text_value) + SELECT + '${record.resourceId}', + '${record.fieldId}', + '${record.value}', + '${record.textValue}' + FROM DUAL + WHERE NOT EXISTS( + select resource_id + from ${tableName} + where resource_id = #{record.resourceId} and field_id = #{record.fieldId} + ) delete from ${tableName} diff --git a/backend/src/main/java/io/metersphere/commons/utils/ServiceUtils.java b/backend/src/main/java/io/metersphere/commons/utils/ServiceUtils.java index a601564831..9873b31d22 100644 --- a/backend/src/main/java/io/metersphere/commons/utils/ServiceUtils.java +++ b/backend/src/main/java/io/metersphere/commons/utils/ServiceUtils.java @@ -21,10 +21,7 @@ import org.mybatis.spring.SqlSessionUtils; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; import java.util.*; -import java.util.function.BiFunction; -import java.util.function.Consumer; -import java.util.function.Function; -import java.util.function.Supplier; +import java.util.function.*; import java.util.stream.Collectors; public class ServiceUtils { @@ -302,6 +299,26 @@ public class ServiceUtils { return sqlSessionFactory.openSession(ExecutorType.BATCH); } + /** + * 批量操作 + */ + public static void batchOperate(List data, int batchSize, Class mapperClazz, BiConsumer operateFunc) { + if (CollectionUtils.isEmpty(data)) { + return; + } + SqlSessionFactory sqlSessionFactory = CommonBeanFactory.getBean(SqlSessionFactory.class); + SqlSession sqlSession = sqlSessionFactory.openSession(ExecutorType.BATCH); + Object mapper = sqlSession.getMapper(mapperClazz); + for (int i = 0; i < data.size(); i++) { + operateFunc.accept(data.get(i), mapper); + if (i % batchSize == 0) { + sqlSession.flushStatements(); + } + } + sqlSession.flushStatements(); + SqlSessionUtils.closeSqlSession(sqlSession, sqlSessionFactory); + } + public static String getCopyName(String name) { return "copy_" + name + "_" + UUID.randomUUID().toString().substring(0, 4); } diff --git a/backend/src/main/java/io/metersphere/commons/utils/SubListUtil.java b/backend/src/main/java/io/metersphere/commons/utils/SubListUtil.java new file mode 100644 index 0000000000..c46736b544 --- /dev/null +++ b/backend/src/main/java/io/metersphere/commons/utils/SubListUtil.java @@ -0,0 +1,26 @@ +package io.metersphere.commons.utils; + +import java.util.List; +import java.util.function.Consumer; + +public class SubListUtil { + + /** + * 将较长的数组截断成较短的数组进行批处理 + */ + public static void dealForSubList(List totalList, Integer batchSize, Consumer subFunc) { + int count = totalList.size(); + int iteratorCount = count / batchSize; + for (int i = 0; i <= iteratorCount; i++) { + int endIndex, startIndex; + startIndex = i * batchSize; + endIndex = ((endIndex = (i + 1) * batchSize) > count) ? count : endIndex; + if (endIndex == startIndex) { + break; + } + List subList = totalList.subList(startIndex, endIndex); + subFunc.accept(subList); + } + } + +} diff --git a/backend/src/main/java/io/metersphere/service/CustomFieldResourceService.java b/backend/src/main/java/io/metersphere/service/CustomFieldResourceService.java index bc8aec938d..6fabe9bb15 100644 --- a/backend/src/main/java/io/metersphere/service/CustomFieldResourceService.java +++ b/backend/src/main/java/io/metersphere/service/CustomFieldResourceService.java @@ -15,9 +15,11 @@ import io.metersphere.commons.constants.TemplateConstants; import io.metersphere.commons.exception.MSException; import io.metersphere.commons.utils.LogUtil; import io.metersphere.commons.utils.ServiceUtils; +import io.metersphere.commons.utils.SubListUtil; import io.metersphere.controller.request.customfield.CustomFieldResourceRequest; import io.metersphere.dto.CustomFieldDao; import io.metersphere.dto.CustomFieldItemDTO; +import io.metersphere.dto.CustomFieldResourceDTO; import io.metersphere.track.dto.CustomFieldResourceCompatibleDTO; import org.apache.commons.collections.CollectionUtils; import org.apache.commons.lang3.StringUtils; @@ -130,6 +132,21 @@ public class CustomFieldResourceService { return extCustomFieldResourceMapper.getByResourceId(tableName, resourceId); } + public void batchUpdateByResourceIds(String tableName, List resourceIds, CustomFieldResourceDTO customField) { + if (CollectionUtils.isEmpty(resourceIds)) { + return; + } + SubListUtil.dealForSubList(resourceIds, 5000, (subIds) -> + extCustomFieldResourceMapper.batchUpdateByResourceIds(tableName, subIds, customField)); + } + + public void batchInsertIfNotExists(String tableName, List resourceIds, CustomFieldResourceDTO customField) { + ServiceUtils.batchOperate(resourceIds, 5000, ExtCustomFieldResourceMapper.class, (resourceId, batchMapper) -> { + customField.setResourceId((String) resourceId); + ((ExtCustomFieldResourceMapper) batchMapper).batchInsertIfNotExists(tableName, customField); + }); + } + protected List getByResourceIds(String tableName, List resourceIds) { if (CollectionUtils.isEmpty(resourceIds)) { return new ArrayList<>(); diff --git a/backend/src/main/java/io/metersphere/service/CustomFieldTestCaseService.java b/backend/src/main/java/io/metersphere/service/CustomFieldTestCaseService.java index c69b5246db..fc3f15a7cf 100644 --- a/backend/src/main/java/io/metersphere/service/CustomFieldTestCaseService.java +++ b/backend/src/main/java/io/metersphere/service/CustomFieldTestCaseService.java @@ -2,6 +2,7 @@ package io.metersphere.service; import io.metersphere.base.domain.ext.CustomFieldResource; import io.metersphere.dto.CustomFieldDao; +import io.metersphere.dto.CustomFieldResourceDTO; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; @@ -45,4 +46,12 @@ public class CustomFieldTestCaseService extends CustomFieldResourceService { public List getByResourceId(String resourceId) { return super.getByResourceId(TABLE_NAME, resourceId); } + + public void batchUpdateByResourceIds(List resourceIds, CustomFieldResourceDTO customField) { + super.batchUpdateByResourceIds(TABLE_NAME, resourceIds, customField); + } + + public void batchInsertIfNotExists(List ids, CustomFieldResourceDTO customField) { + super.batchInsertIfNotExists(TABLE_NAME, ids, customField); + } } diff --git a/backend/src/main/java/io/metersphere/track/service/TestCaseService.java b/backend/src/main/java/io/metersphere/track/service/TestCaseService.java index 83c9a84063..83fe37a90a 100644 --- a/backend/src/main/java/io/metersphere/track/service/TestCaseService.java +++ b/backend/src/main/java/io/metersphere/track/service/TestCaseService.java @@ -1500,6 +1500,9 @@ public class TestCaseService { } public List findByBatchRequest(TestCaseBatchRequest request) { + if (!request.getCondition().isSelectAll()) { + request.getCondition().setIds(request.getIds()); + } return listTestCase(request.getCondition(), true); } @@ -1717,6 +1720,7 @@ public class TestCaseService { String name = customField.getName(); String value = JSONObject.parse(customField.getValue()).toString(); TestCaseWithBLOBs testCaseWithBLOBs = new TestCaseWithBLOBs(); + testCaseWithBLOBs.setUpdateTime(System.currentTimeMillis()); if (StringUtils.equalsAnyIgnoreCase(name, "用例等级")) { testCaseWithBLOBs.setPriority(value); @@ -1733,26 +1737,17 @@ public class TestCaseService { if (CollectionUtils.isEmpty(request.getIds())) { return; } - SqlSession sqlSession = sqlSessionFactory.openSession(ExecutorType.BATCH); - TestCaseMapper mapper = sqlSession.getMapper(TestCaseMapper.class); - List testCases = extTestCaseMapper.getCustomFieldsByIds(request.getIds()); - for (int i = 0; i < testCases.size(); i++) { - TestCaseWithBLOBs testCase = testCases.get(i); - customField.setResourceId(testCase.getId()); - int row = customFieldTestCaseService.updateByPrimaryKeySelective(customField); - if (row < 1) { - customFieldTestCaseService.insert(customField); - } - testCase.setUpdateTime(System.currentTimeMillis()); - TestCaseExample example = new TestCaseExample(); - example.createCriteria().andIdEqualTo(testCase.getId()); - mapper.updateByExampleSelective(testCase, example); - if (i % 1000 == 0) { - sqlSession.flushStatements(); - } + + customFieldTestCaseService.batchUpdateByResourceIds(request.getIds(), customField); + // 如果没有字段,则添加 + customFieldTestCaseService.batchInsertIfNotExists(request.getIds(), customField); + + if (request.getCondition().isSelectAll()) { + // 如果全选,去掉这个查询条件,避免ids过长 + request.getCondition().setIds(null); } - sqlSession.flushStatements(); - SqlSessionUtils.closeSqlSession(sqlSession, sqlSessionFactory); + // 更新修改时间 + bathUpdateByCondition(request, testCaseWithBLOBs); } }