From 02177e65c3443c8714301e4a3d891d7d12cde633 Mon Sep 17 00:00:00 2001
From: yeg <1347747024@qq.com>
Date: 星期三, 09 九月 2026 12:03:44 +0800
Subject: [PATCH] 裁剪修订详情的大字段查询并直接返回记录数量
---
battery-business/src/main/java/com/battery/business/service/impl/TestConsoleDataServiceImpl.java | 2
battery-business/src/main/java/com/battery/business/service/ITestConsoleDataService.java | 2
ruoyi-admin/src/test/java/com/battery/business/web/ConsoleSingleSheetImportDatabaseTest.java | 42 ++++++++++++++++++++
battery-business/src/main/java/com/battery/business/domain/TTestDataRevisionAction.java | 4 ++
battery-business/src/main/resources/mapper/battery/TTestMapper.xml | 11 +++--
ruoyi-admin/src/test/java/com/battery/business/web/ConsoleWorkbookImportMysqlTest.java | 7 +++
6 files changed, 60 insertions(+), 8 deletions(-)
diff --git a/battery-business/src/main/java/com/battery/business/domain/TTestDataRevisionAction.java b/battery-business/src/main/java/com/battery/business/domain/TTestDataRevisionAction.java
index ebfffd0..c54404d 100644
--- a/battery-business/src/main/java/com/battery/business/domain/TTestDataRevisionAction.java
+++ b/battery-business/src/main/java/com/battery/business/domain/TTestDataRevisionAction.java
@@ -18,6 +18,8 @@
private String identitySummary;
private String changesSummary;
private String beforeContentJson;
+ /** 详情展示数量由持久化层统计,非编辑无需加载完整身份数组;不写入审计事实。 */
+ private Long affectedRecordCount;
private String reason;
private Long operatorId;
private String operatorName;
@@ -55,6 +57,8 @@
public String getIdentitySummary() { return identitySummary; }
public void setIdentitySummary(String value) { identitySummary = value; }
public String getChangesSummary() { return changesSummary; }
+ public Long getAffectedRecordCount() { return affectedRecordCount; }
+ public void setAffectedRecordCount(Long value) { affectedRecordCount = value; }
public String getBeforeContentJson() { return beforeContentJson; }
public void setBeforeContentJson(String value) { beforeContentJson = value; }
public void setChangesSummary(String value) { changesSummary = value; }
diff --git a/battery-business/src/main/java/com/battery/business/service/ITestConsoleDataService.java b/battery-business/src/main/java/com/battery/business/service/ITestConsoleDataService.java
index cc81ccd..8fbfc33 100644
--- a/battery-business/src/main/java/com/battery/business/service/ITestConsoleDataService.java
+++ b/battery-business/src/main/java/com/battery/business/service/ITestConsoleDataService.java
@@ -10,7 +10,7 @@
/** 按测试、数据类型、操作类型和时间查询一次用户行为。 */
List<TTestDataRevisionAction> selectActions(TTestDataRevisionAction query);
- /** 返回一条只读修订行为,不恢复被删除的数据。 */
+ /** 返回只读修订摘要及涉及数量;仅编辑附带身份和字段变化,不读取完整修改前快照。 */
TTestDataRevisionAction selectActionById(Long actionId);
diff --git a/battery-business/src/main/java/com/battery/business/service/impl/TestConsoleDataServiceImpl.java b/battery-business/src/main/java/com/battery/business/service/impl/TestConsoleDataServiceImpl.java
index ab77fb4..7bf81d0 100644
--- a/battery-business/src/main/java/com/battery/business/service/impl/TestConsoleDataServiceImpl.java
+++ b/battery-business/src/main/java/com/battery/business/service/impl/TestConsoleDataServiceImpl.java
@@ -38,7 +38,7 @@
return mapper.selectDataRevisionActions(query);
}
- /** 查询修订动作详情及修改前内容。 */
+ /** 查询修订摘要及数量,仅编辑附带展示所需明细,完整修改前快照不进入响应。 */
@Override public TTestDataRevisionAction selectActionById(Long actionId)
{ return mapper.selectDataRevisionActionById(actionId); }
diff --git a/battery-business/src/main/resources/mapper/battery/TTestMapper.xml b/battery-business/src/main/resources/mapper/battery/TTestMapper.xml
index dea8dae..0f82dbb 100644
--- a/battery-business/src/main/resources/mapper/battery/TTestMapper.xml
+++ b/battery-business/src/main/resources/mapper/battery/TTestMapper.xml
@@ -188,11 +188,12 @@
<result property="scopeSummary" column="scope_summary"/><result property="identitySummary" column="identity_summary"/>
<result property="changesSummary" column="changes_summary"/><result property="reason" column="reason"/>
<result property="beforeContentJson" column="before_content_json"/>
+ <result property="affectedRecordCount" column="affected_record_count"/>
<result property="operatorId" column="operator_id"/><result property="operatorName" column="operator_name"/>
<result property="createdAtUtc" column="created_at_utc"/>
</resultMap>
<select id="selectDataRevisionActions" parameterType="com.battery.business.domain.TTestDataRevisionAction" resultMap="TTestDataRevisionActionResultMap">
- <!-- 列表只排序摘要字段;大批次完整 JSON 留给详情查询,避免 MySQL 排序内存耗尽。 -->
+ <!-- 列表只查询和排序摘要字段,不加载批量明细 JSON。 -->
select a.action_id, a.test_id, t.test_name, t.reception_status,
a.data_type, a.operation_type, a.scope_summary, a.reason,
a.operator_id, a.operator_name, a.created_at_utc
@@ -208,11 +209,13 @@
order by a.created_at_utc desc, a.action_id desc
</select>
<select id="selectDataRevisionActionById" parameterType="long" resultMap="TTestDataRevisionActionResultMap">
+ <!-- 非编辑只返回摘要和数量,避免把批量明细加载到服务层;完整审计快照仍留在数据库。 -->
select a.action_id, a.test_id, t.test_name, t.reception_status,
a.data_type, a.operation_type, a.scope_summary,
- cast(a.identity_summary as char) identity_summary,
- cast(a.changes_summary as char) changes_summary, a.reason,
- cast(a.before_content_json as char) before_content_json, a.operator_id, a.operator_name, a.created_at_utc
+ coalesce(json_length(a.identity_summary), 0) affected_record_count,
+ case when a.operation_type = 'EDIT' then cast(a.identity_summary as char) end identity_summary,
+ case when a.operation_type = 'EDIT' then cast(a.changes_summary as char) end changes_summary,
+ a.reason, a.operator_id, a.operator_name, a.created_at_utc
from t_test_data_revision_action a join t_test t on t.test_id = a.test_id
where a.action_id = #{actionId}
</select>
diff --git a/ruoyi-admin/src/test/java/com/battery/business/web/ConsoleSingleSheetImportDatabaseTest.java b/ruoyi-admin/src/test/java/com/battery/business/web/ConsoleSingleSheetImportDatabaseTest.java
index fd609aa..bc52da0 100644
--- a/ruoyi-admin/src/test/java/com/battery/business/web/ConsoleSingleSheetImportDatabaseTest.java
+++ b/ruoyi-admin/src/test/java/com/battery/business/web/ConsoleSingleSheetImportDatabaseTest.java
@@ -25,7 +25,7 @@
import org.springframework.test.util.ReflectionTestUtils;
/** 使用生产 Mapper 和 Spring 事务验证导入;内存数据库不连接共享开发库。 */
-class ConsoleSingleSheetImportDatabaseTest
+public class ConsoleSingleSheetImportDatabaseTest
{
private java.sql.Connection keepAlive;
private TTestController controller;
@@ -38,6 +38,8 @@
var source = new UnpooledDataSource("org.h2.Driver", "jdbc:h2:mem:" + UUID.randomUUID() + ";MODE=MySQL;DATABASE_TO_LOWER=TRUE", "sa", "");
keepAlive = source.getConnection();
jdbc = new JdbcTemplate(source);
+ // H2 无 MySQL JSON_LENGTH;仅在测试中适配计数,真实 SQL 另在 MySQL 验证。
+ jdbc.execute("create alias JSON_LENGTH for 'com.battery.business.web.ConsoleSingleSheetImportDatabaseTest.jsonLength'");
jdbc.execute("create table sys_user(user_id bigint, nick_name varchar(64), del_flag varchar(1))");
jdbc.execute("create table t_test_type(test_type_id bigint, test_type_name varchar(64), del_flag int)");
jdbc.execute("create table t_test(test_id bigint primary key, test_name varchar(100), creator_id bigint, principal_id bigint, test_type_id bigint, test_purpose varchar(100), test_status varchar(20), reception_status varchar(20), monitor_timeout_minutes int, started_at_utc timestamp, reception_boundary_at_utc timestamp, ended_at_utc timestamp, del_flag int default 0, create_by varchar(64), create_time timestamp, update_by varchar(64), update_time timestamp, remark varchar(100), logic_step_mappings_json varchar(100), console_detail_json varchar(100))");
@@ -79,6 +81,15 @@
@AfterEach void closeDatabase() throws Exception { if (keepAlive != null) keepAlive.close(); }
+ /** 模拟 JSON 数组长度;H2 的 JSON 参数可能多包一层字符串。 */
+ public static Integer jsonLength(String value)
+ {
+ if (value == null) return null;
+ Object parsed = JSON.parse(value);
+ if (parsed instanceof String text) parsed = JSON.parse(text);
+ return parsed instanceof List<?> rows ? rows.size() : 1;
+ }
+
@Test void threeTypesPersistActualBindingsTimesAndNumbersAndSkipRetries()
{
for (String type : List.of("REALTIME", "STEP", "CYCLE"))
@@ -106,6 +117,35 @@
assertTrue(service.selectActions(new TTestDataRevisionAction()).isEmpty());
}
+ @Test void importAndDeleteDetailsReturnOnlySummaryWhileAuditRemainsStored() throws Exception
+ {
+ for (String operation : List.of("IMPORT", "DELETE"))
+ {
+ var action = new TTestDataRevisionAction();
+ action.setTestId(1L); action.setDataType("REALTIME"); action.setOperationType(operation);
+ action.setScopeSummary("批量8000条"); action.setReason("摘要查询验证");
+ action.setIdentitySummary(JSON.toJSONString(java.util.stream.IntStream.range(0, 8000).mapToObj(i -> "realtime:" + i).toList()));
+ action.setChangesSummary(JSON.toJSONString(java.util.Collections.nCopies(8000, Map.of("voltage", 1.5))));
+ action.setBeforeContentJson(action.getChangesSummary());
+ mapper.insertDataRevisionAction(action);
+ var summary = service.selectActionById(action.getActionId());
+ assertNull(summary.getIdentitySummary(), "详情查询不得将批量身份 JSON 加载到服务层");
+ assertNull(summary.getChangesSummary(), "详情查询不得将批量变化 JSON 加载到服务层");
+ assertNull(summary.getBeforeContentJson(), "详情查询不得加载完整审计快照");
+ var details = new TTestDataRevisionController();
+ ReflectionTestUtils.setField(details, "service", service);
+ var json = new com.fasterxml.jackson.databind.ObjectMapper();
+ String response = json.writeValueAsString(details.detail(action.getActionId()));
+ assertEquals(8000, json.readTree(response).get("data").get("affectedRecordCount").intValue());
+ assertTrue(response.length() < 1500, "摘要响应不能随批量明细膨胀");
+ // 展示裁剪只发生在 SELECT;数据库审计原文仍完整保留。
+ assertTrue(jdbc.queryForObject("select length(cast(changes_summary as varchar)) from t_test_data_revision_action where action_id=?", Integer.class, action.getActionId()) > 100000);
+ }
+ var list = service.selectActions(new TTestDataRevisionAction());
+ assertEquals(2, list.size());
+ assertTrue(list.stream().allMatch(row -> row.getIdentitySummary() == null && row.getChangesSummary() == null && row.getBeforeContentJson() == null));
+ }
+
@Test void stepMedianVoltagesPersistAndRemainIndependentOfLegacyPeaks()
{
var imported = row();
diff --git a/ruoyi-admin/src/test/java/com/battery/business/web/ConsoleWorkbookImportMysqlTest.java b/ruoyi-admin/src/test/java/com/battery/business/web/ConsoleWorkbookImportMysqlTest.java
index 847668b..08efa77 100644
--- a/ruoyi-admin/src/test/java/com/battery/business/web/ConsoleWorkbookImportMysqlTest.java
+++ b/ruoyi-admin/src/test/java/com/battery/business/web/ConsoleWorkbookImportMysqlTest.java
@@ -106,7 +106,12 @@
var revision = service.selectActionById(actions.get(0).getActionId());
assertEquals(imported.get("actionId"), revision.getActionId());
assertEquals("三 Sheet 共用原因", revision.getReason());
- var changes = JSON.parseArray(revision.getChangesSummary());
+ assertEquals(7767L, revision.getAffectedRecordCount());
+ assertNull(revision.getIdentitySummary());
+ assertNull(revision.getChangesSummary());
+ assertNull(revision.getBeforeContentJson());
+ // 页面仅返回摘要;仍从数据库原文验证三类审计完整保存。
+ var changes = JSON.parseArray(jdbc.queryForObject("select cast(changes_summary as char) from t_test_data_revision_action where action_id=?", String.class, revision.getActionId()));
assertEquals(7767, changes.size());
assertEquals("REALTIME", changes.getJSONObject(0).getString("dataType"));
assertEquals("STEP", changes.getJSONObject(7605).getString("dataType"));
--
Gitblit v1.7.1