From 84dd936b17ff2508ea7b8dac4a48f2e2718641a2 Mon Sep 17 00:00:00 2001 From: vincent Date: Tue, 13 Oct 2026 10:44:14 +0800 Subject: [PATCH 1/8] =?UTF-8?q?=E6=9B=B4=E6=96=B0=E4=BA=86=E5=BC=80?= =?UTF-8?q?=E5=8F=91=E7=8E=AF=E5=A2=83=E7=9A=84=E9=85=8D=E7=BD=AE?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../controller/externalInterface/ApiSignDemo.java | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/zdxt-modules/zdxt-enforcement-code/src/main/java/com/zdxt/enforcementcode/controller/externalInterface/ApiSignDemo.java b/zdxt-modules/zdxt-enforcement-code/src/main/java/com/zdxt/enforcementcode/controller/externalInterface/ApiSignDemo.java index 43de7ae9..57803591 100644 --- a/zdxt-modules/zdxt-enforcement-code/src/main/java/com/zdxt/enforcementcode/controller/externalInterface/ApiSignDemo.java +++ b/zdxt-modules/zdxt-enforcement-code/src/main/java/com/zdxt/enforcementcode/controller/externalInterface/ApiSignDemo.java @@ -14,15 +14,15 @@ import java.util.Map; public class ApiSignDemo { - private static final String APP_KEY = "XXX"; - private static final String APP_SECRET = "XXX"; + private static final String APP_KEY = "4263693515"; + private static final String APP_SECRET = "e4Ugj6LytHX52AXizuNvanwZkVqXAB4J"; private static final String BASE_URL = "http://localhost:8080"; // 平台公钥:加密请求体 - private static final String PLATFORM_PUBLIC_KEY = "XXXXXX"; + private static final String PLATFORM_PUBLIC_KEY = "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQD4u2+dXNQvhTFDJNGvuz4TQAaVpg5Fse0YbPdHbDolpiglbDEuCfuhbekiJiB/9m3h1uArMvXHde26+F8SG2PFjljAmKFuMWkOwH6Zi5Ho7bGRr+nMFZfcEucZOcgb2yMV9RhDrPm5bGtOAgxCf33xKRH08fFzuhZ+T3DvSbpEwQIDAQAB"; // 调用方私钥:解密响应体 - private static final String CALLER_PRIVATE_KEY = "XXXXXX"; + private static final String CALLER_PRIVATE_KEY = "MIICdgIBADANBgkqhkiG9w0BAQEFAASCAmAwggJcAgEAAoGBAK6n1r9N+OSANSVfU6I89EJ+i+fJUNgB4sKdUh/79H/ks1d4gvhsdsytPDkFo27xCz6qw7OtXHJt9vK9KQ/gKMMC+uGoTOWnys8OOn9iGTwZ0DHmzMHrZi6aNZ5DDqO4GzNiro/2h+lZMTDMNTG8zGVuzyFPqQEv7XRq0CmEq76NAgMBAAECgYAaDIlQXgI9nkuO5+FS5LFvi201ZEas+NcHvKwHfi4QtxzyclRiVdcAHuRJAujFvqi1L4Xhsf0EShdXS9QofH/Hmtia7sSqDSzJ06jR4EDucJfUYKfHEcVBroRjjwgGwmtQ6IMp9lVqiqRQWvkwG9xyfPjbqNx/1NvuQ+Mc521kwQJBAOM/a1O9pKS8e/ZT3R2mtDliOuua0y7oT5gq9mqo6HBgDBY/whyxy0MJdnsuKRcgXxu3RBVjq6panNEex1r6D20CQQDEwPR3sRV2ECUQk6k+yDwD1QnkKAbROeGvcp4DSEJwLjNCUkUmL2eQECgFesSTlf1AbGC2NrOaI7L6QsXeklehAkAvXLlmw6C8ANipN0Nfea4YQ6PaFPOs1Bg6s8GV60w+l5YNUQ6I4nllqGQ8OhuwSTvpT+Htv084+xex8gNEr9dlAkBuReL+bm6j1Bqh9tCFkn4oe69mg5SGkVVPGwM6vbYW3531Dt0YsLrvgE6d+5fPS+I7yEJP/cqdmmKGZwQ1YXnhAkEAp6Vd2Q5OXdS/SUezCGf8xhb9SBaPQChgzfgC//N0iug+fDfaSnShHn0LKpBf7yEBvk0M4La7cqnyY233nYHTrQ=="; public static void main(String[] args) throws Exception { System.out.println("========================================"); From fefa6c28e58ab52bc2c070ffd2f780469f677492 Mon Sep 17 00:00:00 2001 From: vincent Date: Tue, 13 Oct 2026 16:24:27 +0800 Subject: [PATCH 2/8] =?UTF-8?q?=E6=9B=B4=E6=96=B0=E4=BA=86=E5=BC=80?= =?UTF-8?q?=E5=8F=91=E7=8E=AF=E5=A2=83=E7=9A=84=E9=85=8D=E7=BD=AE?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- script/sql/vincent/V1.10.1_20261013.sql | 46 ++++ .../common/util/IdCardCryptoUtil.java | 8 +- .../quartz/job/XzjcInfoSyncJob.java | 34 +++ .../service/IXzjcInfoSyncService.java | 6 + .../service/impl/XzjcInfoSyncServiceImpl.java | 207 ++++++++++++++++++ .../zdxt/service/test/XzjcInfoSyncTest.java | 190 ++++++++++++++++ 6 files changed, 487 insertions(+), 4 deletions(-) create mode 100644 script/sql/vincent/V1.10.1_20261013.sql create mode 100644 zdxt-modules/zdxt-enforcement-code/src/main/java/com/zdxt/enforcementcode/quartz/job/XzjcInfoSyncJob.java create mode 100644 zdxt-modules/zdxt-enforcement-code/src/main/java/com/zdxt/enforcementcode/service/IXzjcInfoSyncService.java create mode 100644 zdxt-modules/zdxt-enforcement-code/src/main/java/com/zdxt/enforcementcode/service/impl/XzjcInfoSyncServiceImpl.java create mode 100644 zdxt-web-server/zdxt-admin-web-server/src/test/java/com/zdxt/service/test/XzjcInfoSyncTest.java diff --git a/script/sql/vincent/V1.10.1_20261013.sql b/script/sql/vincent/V1.10.1_20261013.sql new file mode 100644 index 00000000..ea6fe0e3 --- /dev/null +++ b/script/sql/vincent/V1.10.1_20261013.sql @@ -0,0 +1,46 @@ +CREATE TABLE `SZSFJ_ZFJDM_XZJC_INFO` ( + `ID` bigint NOT NULL AUTO_INCREMENT COMMENT '主键,自增ID', + `YWID` varchar(64) NOT NULL COMMENT '业务ID', + `BJQYMC` varchar(128) DEFAULT NULL COMMENT '被检查企业名称', + `BJQYTYSHXYDM` varchar(32) DEFAULT NULL COMMENT '被检查企业统一社会信用代码', + `JCSX` varchar(512) DEFAULT NULL COMMENT '检查事项', + `RQSJ` datetime DEFAULT NULL COMMENT '入企时间', + `ZFYJ` varchar(512) DEFAULT NULL COMMENT '执法依据', + `JCLB` varchar(2) DEFAULT NULL COMMENT '检查类别:1行政检查|2行政处罚|3行政许可|4行政强制|5行政征收|6行政给付|7行政确认|8行政登记|9行政裁决|10文书送达', + `JCYY` varchar(2) DEFAULT NULL COMMENT '检查原因:01日常检查|02投诉举报|03上级交办|04部门移送|05重点领域治理部署|06专项行动|09其它', + `SFLHJC` tinyint DEFAULT NULL COMMENT '是否联合检查:0否,1是', + `LHJCBH` varchar(50) DEFAULT NULL COMMENT '联合检查编号', + `SFWTJC` tinyint DEFAULT NULL COMMENT '是否委托检查:0否,1是', + `WTJCBMMC` varchar(128) DEFAULT NULL COMMENT '委托检查部门名称', + `SFSM` tinyint DEFAULT NULL COMMENT '是否扫码:0是,1否', + `WSMYY` varchar(256) DEFAULT NULL COMMENT '未扫码原因:0其他|1企业原因|2系统原因|3扫码未能显示企业信息|9补录', + `QTYYXXQ` varchar(512) DEFAULT NULL COMMENT '其他原因详情', + `ZFRYXM` varchar(64) DEFAULT NULL COMMENT '执法人员姓名', + `XZZFZH` varchar(64) DEFAULT NULL COMMENT '行政执法证号', + `QTZFRYXM` varchar(64) DEFAULT NULL COMMENT '其他执法人员姓名', + `QTXZZFZH` varchar(64) DEFAULT NULL COMMENT '其他行政执法证号', + `ZFDWMC` varchar(64) DEFAULT NULL COMMENT '执法单位名称', + `ZFBMMC` varchar(64) DEFAULT NULL COMMENT '执法部门名称', + `YWCJSJ` datetime DEFAULT NULL COMMENT '业务创建时间', + `YWXGSJ` datetime DEFAULT NULL COMMENT '业务修改时间', + `CJSJ` datetime DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间', + `XGSJ` datetime DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '修改时间', + PRIMARY KEY (`ID`), + UNIQUE KEY `uk_ywid` (`YWID`), + KEY `idx_bjqy_credit` (`BJQYTYSHXYDM`), + KEY `idx_rqsj` (`RQSJ`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='行政检查信息表'; + +-- 定时任务:每天凌晨2点同步 enforcement_registration 增量数据到 SZSFJ_ZFJDM_XZJC_INFO +INSERT INTO sys_job (job_name, job_group, invoke_target, cron_expression, misfire_policy, concurrent, status, create_by, + create_time, remark) +VALUES ('行政检查信息增量同步', + 'DEFAULT', + 'xzjcInfoSyncJob.execute()', + '0 0 2 * * ?', + '3', + '1', + '0', + 'admin', + NOW(), + '每天凌晨2点将enforcement_registration增量数据同步到SZSFJ_ZFJDM_XZJC_INFO表(市司法局数据共享)'); diff --git a/zdxt-modules/zdxt-enforcement-code/src/main/java/com/zdxt/enforcementcode/common/util/IdCardCryptoUtil.java b/zdxt-modules/zdxt-enforcement-code/src/main/java/com/zdxt/enforcementcode/common/util/IdCardCryptoUtil.java index fb716e27..70a9e7b0 100644 --- a/zdxt-modules/zdxt-enforcement-code/src/main/java/com/zdxt/enforcementcode/common/util/IdCardCryptoUtil.java +++ b/zdxt-modules/zdxt-enforcement-code/src/main/java/com/zdxt/enforcementcode/common/util/IdCardCryptoUtil.java @@ -26,11 +26,11 @@ public class IdCardCryptoUtil { String key = "VRJHzFqJpsSZhwnsKTWNspv_GZMxTWl-bgH6DyE9Ty0"; System.out.println("====================== 示例 ======================"); // 加密 - String source_dec = "15815555985"; - String enc = IdCardCryptoUtil.symmetricEncryptIdCard(key, source_dec); - System.out.println(source_dec+" 加密后 : "+enc); +// String source_dec = "15815555985"; +// String enc = IdCardCryptoUtil.symmetricEncryptIdCard(key, source_dec); +// System.out.println(source_dec+" 加密后 : "+enc); // 解密 - String source_enc = "wDLyWcBO/fIH2rJpSGN98A=="; + String source_enc = "4NF1suqgEdfJZ2KNE7lvgA=="; String dec = IdCardCryptoUtil.symmetricDecryptIdCard(key, source_enc); System.out.println(source_enc+" 解密后 : "+dec); diff --git a/zdxt-modules/zdxt-enforcement-code/src/main/java/com/zdxt/enforcementcode/quartz/job/XzjcInfoSyncJob.java b/zdxt-modules/zdxt-enforcement-code/src/main/java/com/zdxt/enforcementcode/quartz/job/XzjcInfoSyncJob.java new file mode 100644 index 00000000..9f5c3806 --- /dev/null +++ b/zdxt-modules/zdxt-enforcement-code/src/main/java/com/zdxt/enforcementcode/quartz/job/XzjcInfoSyncJob.java @@ -0,0 +1,34 @@ +package com.zdxt.enforcementcode.quartz.job; + +import com.zdxt.enforcementcode.service.IXzjcInfoSyncService; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.springframework.stereotype.Component; + +/** + * 行政检查信息同步定时任务 + *

每天将 enforcement_registration 增量数据同步到 SZSFJ_ZFJDM_XZJC_INFO(市司法局数据共享表)

+ *

默认 cron: 0 0 2 * * ?(每天凌晨 2 点)

+ * + * @author zdxt + */ +@Slf4j +@Component +@RequiredArgsConstructor +public class XzjcInfoSyncJob { + + private final IXzjcInfoSyncService xzjcInfoSyncService; + + /** + * 任务执行入口(public,供 JobInvokeUtil 通过反射调用) + */ + public void execute() { + log.info("[XzjcInfoSyncJob] 定时任务触发:行政检查信息增量同步"); + try { + xzjcInfoSyncService.syncIncremental(); + } catch (Exception e) { + log.error("[XzjcInfoSyncJob] 行政检查信息同步失败", e); + throw e; + } + } +} diff --git a/zdxt-modules/zdxt-enforcement-code/src/main/java/com/zdxt/enforcementcode/service/IXzjcInfoSyncService.java b/zdxt-modules/zdxt-enforcement-code/src/main/java/com/zdxt/enforcementcode/service/IXzjcInfoSyncService.java new file mode 100644 index 00000000..229dd38e --- /dev/null +++ b/zdxt-modules/zdxt-enforcement-code/src/main/java/com/zdxt/enforcementcode/service/IXzjcInfoSyncService.java @@ -0,0 +1,6 @@ +package com.zdxt.enforcementcode.service; + +public interface IXzjcInfoSyncService { + + public int syncIncremental(); +} diff --git a/zdxt-modules/zdxt-enforcement-code/src/main/java/com/zdxt/enforcementcode/service/impl/XzjcInfoSyncServiceImpl.java b/zdxt-modules/zdxt-enforcement-code/src/main/java/com/zdxt/enforcementcode/service/impl/XzjcInfoSyncServiceImpl.java new file mode 100644 index 00000000..59e5eaf1 --- /dev/null +++ b/zdxt-modules/zdxt-enforcement-code/src/main/java/com/zdxt/enforcementcode/service/impl/XzjcInfoSyncServiceImpl.java @@ -0,0 +1,207 @@ +package com.zdxt.enforcementcode.service.impl; + + +import com.zdxt.enforcementcode.service.IXzjcInfoSyncService; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.springframework.jdbc.core.JdbcTemplate; +import org.springframework.stereotype.Service; + +import java.sql.Timestamp; +import java.util.ArrayList; +import java.util.List; +import java.util.Map; + +/** + * 行政检查信息同步服务 + *

增量同步 enforcement_registration -> SZSFJ_ZFJDM_XZJC_INFO(市司法局数据共享表)

+ *

增量水位:目标表 MAX(YWXGSJ),源表 update_time >= 水位即为增量;目标表为空时首次自动全量

+ *

写入策略:基于 uk_ywid 唯一键 INSERT ... ON DUPLICATE KEY UPDATE(幂等)

+ * + * @author zdxt + */ +@Slf4j +@Service +@RequiredArgsConstructor +public class XzjcInfoSyncServiceImpl implements IXzjcInfoSyncService { + + /** 批量写入大小 */ + private static final int BATCH_SIZE = 500; + + private final JdbcTemplate jdbcTemplate; + + /** + * 执行一次增量同步 + * + * @return 处理条数 + */ + public int syncIncremental() { + Timestamp watermark = queryWatermark(); + List> rows = queryIncremental(watermark); + if (rows.isEmpty()) { + log.info("[XzjcInfoSync] 无增量数据, watermark={}", watermark); + return 0; + } + + int affected = 0; + List batch = new ArrayList<>(BATCH_SIZE); + for (Map row : rows) { + batch.add(toParams(row)); + if (batch.size() >= BATCH_SIZE) { + affected += flushBatch(batch); + batch.clear(); + } + } + affected += flushBatch(batch); + + log.info("[XzjcInfoSync] 增量同步完成: 读取 {} 条, 写入 {} 条, watermark={}", rows.size(), affected, watermark); + return rows.size(); + } + + /** + * 增量水位:目标表中已同步数据的最大业务修改时间 + */ + private Timestamp queryWatermark() { + List> list = jdbcTemplate.queryForList( + "SELECT MAX(YWXGSJ) AS watermark FROM SZSFJ_ZFJDM_XZJC_INFO"); + if (list.isEmpty() || list.get(0).get("watermark") == null) { + return null; + } + Object v = list.get(0).get("watermark"); + return v instanceof Timestamp ts ? ts : Timestamp.valueOf(v.toString()); + } + + /** + * 查询源表增量数据(水位为 NULL 时全量) + */ + private List> queryIncremental(Timestamp watermark) { + String sql = """ + SELECT + id, enterprise_name, enterprise_number, + law_enforcement_item_text, law_enforcement_item, + enforcement_time, + law_enforcement_basis_text, law_enforcement_basis, + law_enforce_category, check_category, + has_union, union_no, has_auto, entrust_dept_name, other_reasons, + law_enforcer, law_enforcer_id, + law_enforcer_two, law_enforcer_id_two, + bureau_dept_name, law_enforcement, + create_time, update_time + FROM enforcement_registration + WHERE is_delete = 0 + AND update_time IS NOT NULL + AND (? IS NULL OR update_time >= ?) + ORDER BY update_time ASC, id ASC + """; + return jdbcTemplate.queryForList(sql, watermark, watermark); + } + + /** + * 批量 upsert(uk_ywid 冲突时更新) + */ + private int flushBatch(List batch) { + if (batch.isEmpty()) { + return 0; + } + String sql = """ + INSERT INTO SZSFJ_ZFJDM_XZJC_INFO + (YWID, BJQYMC, BJQYTYSHXYDM, JCSX, RQSJ, ZFYJ, JCLB, JCYY, + SFLHJC, LHJCBH, SFWTJC, WTJCBMMC, QTYYXXQ, + ZFRYXM, XZZFZH, QTZFRYXM, QTXZZFZH, ZFDWMC, ZFBMMC, YWCJSJ, YWXGSJ) + VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?) + ON DUPLICATE KEY UPDATE + BJQYMC = VALUES(BJQYMC), + BJQYTYSHXYDM = VALUES(BJQYTYSHXYDM), + JCSX = VALUES(JCSX), + RQSJ = VALUES(RQSJ), + ZFYJ = VALUES(ZFYJ), + JCLB = VALUES(JCLB), + JCYY = VALUES(JCYY), + SFLHJC = VALUES(SFLHJC), + LHJCBH = VALUES(LHJCBH), + SFWTJC = VALUES(SFWTJC), + WTJCBMMC = VALUES(WTJCBMMC), + QTYYXXQ = VALUES(QTYYXXQ), + ZFRYXM = VALUES(ZFRYXM), + XZZFZH = VALUES(XZZFZH), + QTZFRYXM = VALUES(QTZFRYXM), + QTXZZFZH = VALUES(QTXZZFZH), + ZFDWMC = VALUES(ZFDWMC), + ZFBMMC = VALUES(ZFBMMC), + YWCJSJ = VALUES(YWCJSJ), + YWXGSJ = VALUES(YWXGSJ) + """; + int[] results = jdbcTemplate.batchUpdate(sql, batch); + int affected = 0; + for (int r : results) { + affected += r; + } + return affected; + } + + /** + * 源表行 -> 目标表参数(字段映射与长度截断) + */ + private Object[] toParams(Map row) { + Long hasUnion = toLong(row.get("has_union")); + Long hasAuto = toLong(row.get("has_auto")); + String unionNo = str(row.get("union_no")); + // 联合检查判定:has_union=1 且 union_no 不为空 + boolean isUnion = hasUnion != null && hasUnion == 1 && !unionNo.isEmpty(); + + return new Object[]{ + str(row.get("id")), + fit(row.get("enterprise_name"), 128), + fit(row.get("enterprise_number"), 32), + fit(coalesce(row, "law_enforcement_item_text", "law_enforcement_item"), 512), + row.get("enforcement_time"), + fit(coalesce(row, "law_enforcement_basis_text", "law_enforcement_basis"), 512), + fit(row.get("law_enforce_category"), 2), + fit(row.get("check_category"), 2), + isUnion ? 1 : 0, + fit(unionNo, 50), + hasAuto != null && hasAuto == 1 ? 1 : 0, + fit(row.get("entrust_dept_name"), 128), + fit(row.get("other_reasons"), 512), + fit(row.get("law_enforcer"), 64), + fit(row.get("law_enforcer_id"), 64), + fit(row.get("law_enforcer_two"), 64), + fit(row.get("law_enforcer_id_two"), 64), + fit(row.get("bureau_dept_name"), 64), + fit(row.get("law_enforcement"), 64), + row.get("create_time"), + row.get("update_time") + }; + } + + private Object coalesce(Map row, String first, String second) { + Object v = row.get(first); + return v != null ? v : row.get(second); + } + + private String str(Object v) { + return v == null ? null : v.toString(); + } + + private String fit(Object v, int maxLen) { + String s = str(v); + if (s != null && s.length() > maxLen) { + return s.substring(0, maxLen); + } + return s; + } + + private Long toLong(Object v) { + if (v == null) { + return null; + } + if (v instanceof Number n) { + return n.longValue(); + } + try { + return Long.valueOf(v.toString()); + } catch (NumberFormatException e) { + return null; + } + } +} diff --git a/zdxt-web-server/zdxt-admin-web-server/src/test/java/com/zdxt/service/test/XzjcInfoSyncTest.java b/zdxt-web-server/zdxt-admin-web-server/src/test/java/com/zdxt/service/test/XzjcInfoSyncTest.java new file mode 100644 index 00000000..e269ec1f --- /dev/null +++ b/zdxt-web-server/zdxt-admin-web-server/src/test/java/com/zdxt/service/test/XzjcInfoSyncTest.java @@ -0,0 +1,190 @@ +package com.zdxt.service.test; + +import com.zdxt.enforcementcode.service.impl.XzjcInfoSyncServiceImpl; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import org.mockito.ArgumentCaptor; +import org.mockito.ArgumentMatchers; +import org.mockito.InjectMocks; +import org.mockito.Mock; +import org.mockito.junit.jupiter.MockitoExtension; +import org.springframework.jdbc.core.JdbcTemplate; + +import java.sql.Timestamp; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import static org.junit.jupiter.api.Assertions.*; +import static org.mockito.ArgumentMatchers.*; +import static org.mockito.Mockito.*; + +/** + * {@link XzjcInfoSyncServiceImpl#syncIncremental()} 单元测试 + *

+ * 通过 mock JdbcTemplate 验证增量水位、批量 upsert 与字段映射等正向流程,不依赖真实数据库。 + *

+ * + * @author zdxt + */ +@ExtendWith(MockitoExtension.class) +@DisplayName("行政检查信息增量同步 单元测试") +class XzjcInfoSyncTest { + + @Mock + private JdbcTemplate jdbcTemplate; + + @InjectMocks + private XzjcInfoSyncServiceImpl syncService; + + // ======================== 增量水位 ======================== +// +// @Test +// @DisplayName("源表无增量数据时返回 0 且不执行写入") +// void testSyncWhenNoIncrementalData() { +// when(jdbcTemplate.queryForList(anyString())) +// .thenReturn(List.of(watermarkMap(Timestamp.valueOf("2026-10-13 09:00:00")))); +// when(jdbcTemplate.queryForList(anyString(), any(Object[].class))) +// .thenReturn(new ArrayList<>()); +// +// int count = syncService.syncIncremental(); +// +// assertEquals(0, count, "无增量时应返回 0"); +// verify(jdbcTemplate, never()).batchUpdate(anyString(), anyList()); +// } + + @Test + @DisplayName("目标表为空时水位为 null,触发全量查询") + void testFullScanWhenTargetTableEmpty() { + when(jdbcTemplate.queryForList(anyString())).thenReturn(new ArrayList<>()); + when(jdbcTemplate.queryForList(anyString(), any(Object[].class))) + .thenReturn(List.of(row("1", "全量企业"))); + when(jdbcTemplate.batchUpdate(anyString(), ArgumentMatchers.>any())) + .thenReturn(new int[]{1}); + + int count = syncService.syncIncremental(); + + assertEquals(1, count); + ArgumentCaptor argsCaptor = ArgumentCaptor.forClass(Object[].class); + verify(jdbcTemplate).queryForList(anyString(), argsCaptor.capture()); + Object[] args = argsCaptor.getValue(); + assertEquals(2, args.length, "增量查询应传 2 个水位参数"); + assertNull(args[0], "目标表为空时水位应为 null"); + assertNull(args[1], "目标表为空时水位应为 null"); + } +// +// // ======================== 同步主流程 ======================== +// +// @Test +// @DisplayName("有增量数据时正常批量 upsert 并返回处理条数") +// void testSyncWithIncrementalData() { +// when(jdbcTemplate.queryForList(anyString())) +// .thenReturn(List.of(watermarkMap(Timestamp.valueOf("2026-10-13 09:00:00")))); +// when(jdbcTemplate.queryForList(anyString(), any(Object[].class))) +// .thenReturn(List.of(row("1", "企业A"), row("2", "企业B"))); +// when(jdbcTemplate.batchUpdate(anyString(), ArgumentMatchers.>any())) +// .thenReturn(new int[]{1, 1}); +// +// int count = syncService.syncIncremental(); +// +// assertEquals(2, count, "返回处理条数应为源表行数"); +// ArgumentCaptor sqlCaptor = ArgumentCaptor.forClass(String.class); +// ArgumentCaptor> batchCaptor = ArgumentCaptor.forClass(List.class); +// verify(jdbcTemplate, times(1)).batchUpdate(sqlCaptor.capture(), batchCaptor.capture()); +// assertTrue(sqlCaptor.getValue().contains("ON DUPLICATE KEY UPDATE"), +// "写入 SQL 应为幂等 upsert"); +// assertEquals(2, batchCaptor.getValue().size(), "批次大小应与增量行数一致"); +// } +// +// @Test +// @DisplayName("超过批量大小 500 时按批次分批写入") +// void testBatchSplit() { +// when(jdbcTemplate.queryForList(anyString())) +// .thenReturn(List.of(watermarkMap(Timestamp.valueOf("2026-10-13 09:00:00")))); +// List> rows = new ArrayList<>(); +// for (int i = 0; i < 501; i++) { +// rows.add(row(String.valueOf(i), "企业" + i)); +// } +// when(jdbcTemplate.queryForList(anyString(), any(Object[].class))).thenReturn(rows); +// when(jdbcTemplate.batchUpdate(anyString(), ArgumentMatchers.>any())) +// .thenReturn(new int[]{500}, new int[]{1}); +// +// int count = syncService.syncIncremental(); +// +// assertEquals(501, count, "返回处理条数应为源表行数"); +// ArgumentCaptor> batchCaptor = ArgumentCaptor.forClass(List.class); +// verify(jdbcTemplate, times(2)).batchUpdate(anyString(), batchCaptor.capture()); +// assertEquals(500, batchCaptor.getAllValues().get(0).size(), "第一批应为 500 条"); +// assertEquals(1, batchCaptor.getAllValues().get(1).size(), "第二批应为 1 条"); +// } +// +// // ======================== 字段映射 ======================== +// +// @Test +// @DisplayName("字段映射正确:联合检查、委托执法与超长截断") +// void testFieldMapping() { +// when(jdbcTemplate.queryForList(anyString())) +// .thenReturn(List.of(watermarkMap(Timestamp.valueOf("2026-10-13 09:00:00")))); +// Map source = row("100", "A".repeat(200)); +// source.put("has_union", 1); +// source.put("union_no", "U100"); +// source.put("has_auto", 1); +// source.put("entrust_dept_name", "委托部门"); +// when(jdbcTemplate.queryForList(anyString(), any(Object[].class))) +// .thenReturn(List.of(source)); +// when(jdbcTemplate.batchUpdate(anyString(), ArgumentMatchers.>any())) +// .thenReturn(new int[]{1}); +// +// syncService.syncIncremental(); +// +// ArgumentCaptor> batchCaptor = ArgumentCaptor.forClass(List.class); +// verify(jdbcTemplate).batchUpdate(anyString(), batchCaptor.capture()); +// Object[] p = batchCaptor.getValue().get(0); +// +// assertEquals("100", p[0], "YWID 应为源表 id"); +// assertEquals(128, String.valueOf(p[1]).length(), "BJQYMC 应截断到 128"); +// assertEquals("检查事项文本", p[3], "JCSX 应为 law_enforcement_item_text"); +// assertEquals(1, p[8], "has_union=1 且 union_no 非空时 SFLHJC 应为 1"); +// assertEquals("U100", p[9], "LHJCBH 应为 union_no"); +// assertEquals(1, p[10], "has_auto=1 时 SFWTJC 应为 1"); +// assertEquals("委托部门", p[11], "WTJCBMMC 应为 entrust_dept_name"); +// } +// +// // ======================== 辅助方法 ======================== +// +// private Map watermarkMap(Timestamp ts) { +// Map m = new HashMap<>(); +// m.put("watermark", ts); +// return m; +// } + + private Map row(String id, String enterpriseName) { + Map m = new HashMap<>(); + m.put("id", id); + m.put("enterprise_name", enterpriseName); + m.put("enterprise_number", "91330000TEST"); + m.put("law_enforcement_item_text", "检查事项文本"); + m.put("law_enforcement_item", "检查事项"); + m.put("enforcement_time", Timestamp.valueOf("2026-10-13 10:00:00")); + m.put("law_enforcement_basis_text", "依据文本"); + m.put("law_enforcement_basis", "依据"); + m.put("law_enforce_category", "1"); + m.put("check_category", "2"); + m.put("has_union", 0); + m.put("union_no", null); + m.put("has_auto", 0); + m.put("entrust_dept_name", "委托部门"); + m.put("other_reasons", "其他原因"); + m.put("law_enforcer", "张三"); + m.put("law_enforcer_id", "Z001"); + m.put("law_enforcer_two", "李四"); + m.put("law_enforcer_id_two", "Z002"); + m.put("bureau_dept_name", "执法局"); + m.put("law_enforcement", "市场监督管理局"); + m.put("create_time", Timestamp.valueOf("2026-10-13 09:00:00")); + m.put("update_time", Timestamp.valueOf("2026-10-13 09:30:00")); + return m; + } +} From 603cf92a660252bfc7a4195bbd263d8d169f75ce Mon Sep 17 00:00:00 2001 From: vincent Date: Wed, 21 Oct 2026 09:15:45 +0800 Subject: [PATCH 3/8] =?UTF-8?q?=E4=BC=98=E5=8C=96=E7=9A=84=E7=BC=96?= =?UTF-8?q?=E7=9B=AE=E7=9A=84=E7=9B=B8=E5=85=B3=E5=8A=9F=E8=83=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../domain/bo/XzjcInfoSyncBo.java | 77 +++++ .../mapper/XzjcInfoSyncMapper.java | 46 +++ .../service/impl/XzjcInfoSyncServiceImpl.java | 263 ++++++++++-------- .../enforcementcode/XzjcInfoSyncMapper.xml | 89 ++++++ .../zdxt/service/test/XzjcInfoSyncTest.java | 37 ++- 5 files changed, 388 insertions(+), 124 deletions(-) create mode 100644 zdxt-modules/zdxt-enforcement-code/src/main/java/com/zdxt/enforcementcode/domain/bo/XzjcInfoSyncBo.java create mode 100644 zdxt-modules/zdxt-enforcement-code/src/main/java/com/zdxt/enforcementcode/mapper/XzjcInfoSyncMapper.java create mode 100644 zdxt-modules/zdxt-enforcement-code/src/main/resources/mapper/enforcementcode/XzjcInfoSyncMapper.xml diff --git a/zdxt-modules/zdxt-enforcement-code/src/main/java/com/zdxt/enforcementcode/domain/bo/XzjcInfoSyncBo.java b/zdxt-modules/zdxt-enforcement-code/src/main/java/com/zdxt/enforcementcode/domain/bo/XzjcInfoSyncBo.java new file mode 100644 index 00000000..8f138fc1 --- /dev/null +++ b/zdxt-modules/zdxt-enforcement-code/src/main/java/com/zdxt/enforcementcode/domain/bo/XzjcInfoSyncBo.java @@ -0,0 +1,77 @@ +package com.zdxt.enforcementcode.domain.bo; + +import lombok.Data; + +import java.util.Date; + +/** + * 行政检查信息同步写入行(对应市司法局数据共享表 SZSFJ_ZFJDM_XZJC_INFO) + * + * @author zdxt + */ +@Data +public class XzjcInfoSyncBo { + + /** 业务ID(YWID) */ + private String ywid; + + /** 被检查企业名称(BJQYMC) */ + private String bjqymc; + + /** 被检查企业统一社会信用代码(BJQYTYSHXYDM) */ + private String bjqytyshxydm; + + /** 检查事项(JCSX) */ + private String jcsx; + + /** 入企时间(RQSJ) */ + private Date rqsj; + + /** 执法依据(ZFYJ) */ + private String zfyj; + + /** 检查类别(JCLB) */ + private String jclb; + + /** 检查原因(JCYY) */ + private String jcyy; + + /** 是否联合检查:0否,1是(SFLHJC) */ + private Integer sflhjc; + + /** 联合检查编号(LHJCBH) */ + private String lhjcbh; + + /** 是否委托检查:0否,1是(SFWTJC) */ + private Integer sfwtjc; + + /** 委托检查部门名称(WTJCBMMC) */ + private String wtjcbmmc; + + /** 其他原因详情(QTYYXXQ) */ + private String qtyyxxq; + + /** 执法人员姓名(ZFRYXM) */ + private String zfryxm; + + /** 行政执法证号(XZZFZH) */ + private String xzzfzh; + + /** 其他执法人员姓名(QTZFRYXM) */ + private String qtzfryxm; + + /** 其他行政执法证号(QTXZZFZH) */ + private String qtxzzfzh; + + /** 执法单位名称(ZFDWMC) */ + private String zfdwmc; + + /** 执法部门名称(ZFBMMC) */ + private String zfbmmc; + + /** 业务创建时间(YWCJSJ) */ + private Date ywcjsj; + + /** 业务修改时间(YWXGSJ) */ + private Date ywxgsj; +} diff --git a/zdxt-modules/zdxt-enforcement-code/src/main/java/com/zdxt/enforcementcode/mapper/XzjcInfoSyncMapper.java b/zdxt-modules/zdxt-enforcement-code/src/main/java/com/zdxt/enforcementcode/mapper/XzjcInfoSyncMapper.java new file mode 100644 index 00000000..6769824a --- /dev/null +++ b/zdxt-modules/zdxt-enforcement-code/src/main/java/com/zdxt/enforcementcode/mapper/XzjcInfoSyncMapper.java @@ -0,0 +1,46 @@ +package com.zdxt.enforcementcode.mapper; + +import com.zdxt.enforcementcode.domain.bo.XzjcInfoSyncBo; +import org.apache.ibatis.annotations.Param; + +import java.util.Date; +import java.util.List; +import java.util.Map; + +/** + * 行政检查信息同步 Mapper 接口 + *

增量同步 enforcement_registration -> SZSFJ_ZFJDM_XZJC_INFO(市司法局数据共享表)

+ * + * @author zdxt + */ +public interface XzjcInfoSyncMapper { + + /** + * 查询增量水位:目标表已同步数据的最大业务修改时间(MAX(YWXGSJ)) + * + * @return 水位时间;目标表为空时返回 null + */ + Date selectWatermark(); + + /** + * 按 (update_time, id) 键集分页查询源表增量数据 + * + * @param cursorTime 游标时间(null 时全量) + * @param cursorId 游标 ID(cursorTime 非空且本参数为 null 时,按 update_time >= cursorTime 含边界防漏) + * @param endTime 截止时间(上界,不含),只同步该时间之前的数据(通常为今天零点,即前一天晚上的数据) + * @param pageSize 分页大小 + * @return 增量数据行(列为 enforcement_registration 小写列名) + */ + List> selectIncrementalPage(@Param("cursorTime") Date cursorTime, + @Param("cursorId") String cursorId, + @Param("endTime") Date endTime, + @Param("pageSize") int pageSize); + + /** + * 批量 upsert 目标表(基于 uk_ywid 唯一键 INSERT ... ON DUPLICATE KEY UPDATE,幂等) + * + * @param list 写入行集合 + * @return 影响行数(MySQL upsert 语义,不代表真实写入条数) + */ + int upsertBatch(@Param("list") List list); +} diff --git a/zdxt-modules/zdxt-enforcement-code/src/main/java/com/zdxt/enforcementcode/service/impl/XzjcInfoSyncServiceImpl.java b/zdxt-modules/zdxt-enforcement-code/src/main/java/com/zdxt/enforcementcode/service/impl/XzjcInfoSyncServiceImpl.java index 59e5eaf1..33b87394 100644 --- a/zdxt-modules/zdxt-enforcement-code/src/main/java/com/zdxt/enforcementcode/service/impl/XzjcInfoSyncServiceImpl.java +++ b/zdxt-modules/zdxt-enforcement-code/src/main/java/com/zdxt/enforcementcode/service/impl/XzjcInfoSyncServiceImpl.java @@ -1,22 +1,32 @@ package com.zdxt.enforcementcode.service.impl; +import com.zdxt.enforcementcode.domain.bo.XzjcInfoSyncBo; +import com.zdxt.enforcementcode.mapper.XzjcInfoSyncMapper; import com.zdxt.enforcementcode.service.IXzjcInfoSyncService; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; -import org.springframework.jdbc.core.JdbcTemplate; +import org.redisson.api.RLock; +import org.redisson.api.RedissonClient; import org.springframework.stereotype.Service; import java.sql.Timestamp; +import java.time.LocalDate; +import java.time.LocalDateTime; import java.util.ArrayList; +import java.util.Date; import java.util.List; import java.util.Map; +import java.util.concurrent.TimeUnit; /** * 行政检查信息同步服务 *

增量同步 enforcement_registration -> SZSFJ_ZFJDM_XZJC_INFO(市司法局数据共享表)

*

增量水位:目标表 MAX(YWXGSJ),源表 update_time >= 水位即为增量;目标表为空时首次自动全量

*

写入策略:基于 uk_ywid 唯一键 INSERT ... ON DUPLICATE KEY UPDATE(幂等)

+ *

读取策略:(update_time, id) 键集分页,单页单批,避免一次性加载全量数据导致内存溢出

+ *

并发控制:Redisson 分布式锁,覆盖 Quartz 调度重叠、手动触发及多实例部署场景

+ *

SQL 定义见 mapper/enforcementcode/XzjcInfoSyncMapper.xml

* * @author zdxt */ @@ -25,153 +35,144 @@ import java.util.Map; @RequiredArgsConstructor public class XzjcInfoSyncServiceImpl implements IXzjcInfoSyncService { - /** 批量写入大小 */ - private static final int BATCH_SIZE = 500; + /** 分页读取大小(与批量写入大小一致,一页一批) */ + private static final int PAGE_SIZE = 500; - private final JdbcTemplate jdbcTemplate; + /** 单次任务最大分页数,防止异常场景下扫描失控(500*1000=单次最多约 50 万条,剩余下次任务继续) */ + private static final int MAX_PAGES = 1000; + + /** 同步分布式锁 key */ + private static final String LOCK_KEY = "xzjc_info_sync:lock"; + + private final XzjcInfoSyncMapper xzjcInfoSyncMapper; + + private final RedissonClient redissonClient; /** * 执行一次增量同步 + *

通过 Redis 分布式锁保证同一时刻仅一个任务实例在执行(含多实例部署场景)

* - * @return 处理条数 + * @return 处理条数;未获取到锁(上一次仍在执行)或被中断时返回 0 */ public int syncIncremental() { - Timestamp watermark = queryWatermark(); - List> rows = queryIncremental(watermark); - if (rows.isEmpty()) { - log.info("[XzjcInfoSync] 无增量数据, watermark={}", watermark); + RLock lock = redissonClient.getLock(LOCK_KEY); + boolean locked = false; + try { + // 等待 0 秒:抢不到立即返回,不阻塞 Quartz 线程;leaseTime=-1 启用看门狗自动续期,避免长任务锁提前过期 + locked = lock.tryLock(0, -1, TimeUnit.SECONDS); + if (!locked) { + log.warn("[XzjcInfoSync] 上一次同步尚未结束(锁被占用),本次触发跳过"); + return 0; + } + return doSync(); + } catch (InterruptedException e) { + Thread.currentThread().interrupt(); + log.error("[XzjcInfoSync] 同步任务获取锁时被中断", e); return 0; - } - - int affected = 0; - List batch = new ArrayList<>(BATCH_SIZE); - for (Map row : rows) { - batch.add(toParams(row)); - if (batch.size() >= BATCH_SIZE) { - affected += flushBatch(batch); - batch.clear(); + } finally { + if (locked && lock.isHeldByCurrentThread()) { + lock.unlock(); } } - affected += flushBatch(batch); - - log.info("[XzjcInfoSync] 增量同步完成: 读取 {} 条, 写入 {} 条, watermark={}", rows.size(), affected, watermark); - return rows.size(); } /** - * 增量水位:目标表中已同步数据的最大业务修改时间 + * 分页增量同步主体 */ - private Timestamp queryWatermark() { - List> list = jdbcTemplate.queryForList( - "SELECT MAX(YWXGSJ) AS watermark FROM SZSFJ_ZFJDM_XZJC_INFO"); - if (list.isEmpty() || list.get(0).get("watermark") == null) { - return null; + private int doSync() { + // 数据截止时间:今天零点(即只同步前一天晚上 23:59:59 及更早的数据),避免同步当日仍在变化的数据 + Date endTime = Timestamp.valueOf(LocalDate.now().atStartOfDay()); + Date watermark = xzjcInfoSyncMapper.selectWatermark(); + Date cursorTime = watermark; + String cursorId = null; + int total = 0; + boolean limitReached = false; + + for (int page = 1; page <= MAX_PAGES; page++) { + List> rows = xzjcInfoSyncMapper.selectIncrementalPage(cursorTime, cursorId, endTime, PAGE_SIZE); + if (rows.isEmpty()) { + break; + } + + List batch = new ArrayList<>(rows.size()); + for (Map row : rows) { + batch.add(toBo(row)); + } + upsertSafely(batch); + total += rows.size(); + + // 游标推进到本页最后一条,下页从其后继续 + Map last = rows.get(rows.size() - 1); + cursorTime = toTimestamp(last.get("update_time")); + cursorId = str(last.get("id")); + log.info("[XzjcInfoSync] 第 {} 页完成, 累计 {} 条, 游标=({}, {})", page, total, cursorTime, cursorId); + + if (rows.size() < PAGE_SIZE) { + break; + } + if (page == MAX_PAGES) { + limitReached = true; + } } - Object v = list.get(0).get("watermark"); - return v instanceof Timestamp ts ? ts : Timestamp.valueOf(v.toString()); - } - /** - * 查询源表增量数据(水位为 NULL 时全量) - */ - private List> queryIncremental(Timestamp watermark) { - String sql = """ - SELECT - id, enterprise_name, enterprise_number, - law_enforcement_item_text, law_enforcement_item, - enforcement_time, - law_enforcement_basis_text, law_enforcement_basis, - law_enforce_category, check_category, - has_union, union_no, has_auto, entrust_dept_name, other_reasons, - law_enforcer, law_enforcer_id, - law_enforcer_two, law_enforcer_id_two, - bureau_dept_name, law_enforcement, - create_time, update_time - FROM enforcement_registration - WHERE is_delete = 0 - AND update_time IS NOT NULL - AND (? IS NULL OR update_time >= ?) - ORDER BY update_time ASC, id ASC - """; - return jdbcTemplate.queryForList(sql, watermark, watermark); + if (limitReached) { + log.warn("[XzjcInfoSync] 达到单次最大分页数 {}(约 {} 条), 剩余数据下次任务继续同步", MAX_PAGES, (long) MAX_PAGES * PAGE_SIZE); + } + log.info("[XzjcInfoSync] 增量同步完成: 共处理 {} 条, 起始水位={}, 截止={}", total, watermark, endTime); + return total; } /** - * 批量 upsert(uk_ywid 冲突时更新) + * 页级批量 upsert;整批失败时降级为逐条写入,跳过脏数据行,避免单行异常导致游标卡死 */ - private int flushBatch(List batch) { - if (batch.isEmpty()) { - return 0; - } - String sql = """ - INSERT INTO SZSFJ_ZFJDM_XZJC_INFO - (YWID, BJQYMC, BJQYTYSHXYDM, JCSX, RQSJ, ZFYJ, JCLB, JCYY, - SFLHJC, LHJCBH, SFWTJC, WTJCBMMC, QTYYXXQ, - ZFRYXM, XZZFZH, QTZFRYXM, QTXZZFZH, ZFDWMC, ZFBMMC, YWCJSJ, YWXGSJ) - VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?) - ON DUPLICATE KEY UPDATE - BJQYMC = VALUES(BJQYMC), - BJQYTYSHXYDM = VALUES(BJQYTYSHXYDM), - JCSX = VALUES(JCSX), - RQSJ = VALUES(RQSJ), - ZFYJ = VALUES(ZFYJ), - JCLB = VALUES(JCLB), - JCYY = VALUES(JCYY), - SFLHJC = VALUES(SFLHJC), - LHJCBH = VALUES(LHJCBH), - SFWTJC = VALUES(SFWTJC), - WTJCBMMC = VALUES(WTJCBMMC), - QTYYXXQ = VALUES(QTYYXXQ), - ZFRYXM = VALUES(ZFRYXM), - XZZFZH = VALUES(XZZFZH), - QTZFRYXM = VALUES(QTZFRYXM), - QTXZZFZH = VALUES(QTXZZFZH), - ZFDWMC = VALUES(ZFDWMC), - ZFBMMC = VALUES(ZFBMMC), - YWCJSJ = VALUES(YWCJSJ), - YWXGSJ = VALUES(YWXGSJ) - """; - int[] results = jdbcTemplate.batchUpdate(sql, batch); - int affected = 0; - for (int r : results) { - affected += r; + private void upsertSafely(List batch) { + try { + xzjcInfoSyncMapper.upsertBatch(batch); + } catch (Exception e) { + log.error("[XzjcInfoSync] 批量写入失败,降级逐条写入排查脏数据, 批次大小={}", batch.size(), e); + for (XzjcInfoSyncBo bo : batch) { + try { + xzjcInfoSyncMapper.upsertBatch(List.of(bo)); + } catch (Exception rowEx) { + log.error("[XzjcInfoSync] 脏数据跳过: ywid={}", bo.getYwid(), rowEx); + } + } } - return affected; } /** - * 源表行 -> 目标表参数(字段映射与长度截断) + * 源表行 -> 目标表写入行(字段映射与长度截断) */ - private Object[] toParams(Map row) { + private XzjcInfoSyncBo toBo(Map row) { Long hasUnion = toLong(row.get("has_union")); Long hasAuto = toLong(row.get("has_auto")); String unionNo = str(row.get("union_no")); // 联合检查判定:has_union=1 且 union_no 不为空 - boolean isUnion = hasUnion != null && hasUnion == 1 && !unionNo.isEmpty(); - - return new Object[]{ - str(row.get("id")), - fit(row.get("enterprise_name"), 128), - fit(row.get("enterprise_number"), 32), - fit(coalesce(row, "law_enforcement_item_text", "law_enforcement_item"), 512), - row.get("enforcement_time"), - fit(coalesce(row, "law_enforcement_basis_text", "law_enforcement_basis"), 512), - fit(row.get("law_enforce_category"), 2), - fit(row.get("check_category"), 2), - isUnion ? 1 : 0, - fit(unionNo, 50), - hasAuto != null && hasAuto == 1 ? 1 : 0, - fit(row.get("entrust_dept_name"), 128), - fit(row.get("other_reasons"), 512), - fit(row.get("law_enforcer"), 64), - fit(row.get("law_enforcer_id"), 64), - fit(row.get("law_enforcer_two"), 64), - fit(row.get("law_enforcer_id_two"), 64), - fit(row.get("bureau_dept_name"), 64), - fit(row.get("law_enforcement"), 64), - row.get("create_time"), - row.get("update_time") - }; + boolean isUnion = hasUnion != null && hasUnion == 1 && unionNo != null && !unionNo.isEmpty(); + + XzjcInfoSyncBo bo = new XzjcInfoSyncBo(); + bo.setYwid(str(row.get("id"))); + bo.setBjqymc(fit(row.get("enterprise_name"), 128)); + bo.setBjqytyshxydm(fit(row.get("enterprise_number"), 32)); + bo.setJcsx(fit(coalesce(row, "law_enforcement_item_text", "law_enforcement_item"), 512)); + bo.setRqsj(toDate(row.get("enforcement_time"))); + bo.setZfyj(fit(coalesce(row, "law_enforcement_basis_text", "law_enforcement_basis"), 512)); + bo.setJclb(fit(row.get("law_enforce_category"), 2)); + bo.setJcyy(fit(row.get("check_category"), 2)); + bo.setSflhjc(isUnion ? 1 : 0); + bo.setLhjcbh(fit(unionNo, 50)); + bo.setSfwtjc(hasAuto != null && hasAuto == 1 ? 1 : 0); + bo.setWtjcbmmc(fit(row.get("entrust_dept_name"), 128)); + bo.setQtyyxxq(fit(row.get("other_reasons"), 512)); + bo.setZfryxm(fit(row.get("law_enforcer"), 64)); + bo.setXzzfzh(fit(row.get("law_enforcer_id"), 64)); + bo.setQtzfryxm(fit(row.get("law_enforcer_two"), 64)); + bo.setQtxzzfzh(fit(row.get("law_enforcer_id_two"), 64)); + bo.setZfdwmc(fit(row.get("bureau_dept_name"), 64)); + bo.setZfbmmc(fit(row.get("law_enforcement"), 64)); + bo.setYwcjsj(toDate(row.get("create_time"))); + bo.setYwxgsj(toDate(row.get("update_time"))); + return bo; } private Object coalesce(Map row, String first, String second) { @@ -204,4 +205,28 @@ public class XzjcInfoSyncServiceImpl implements IXzjcInfoSyncService { return null; } } + + /** + * 时间类型兼容转换(Timestamp / LocalDateTime / 字符串) + */ + private Timestamp toTimestamp(Object v) { + if (v == null) { + return null; + } + if (v instanceof Timestamp ts) { + return ts; + } + if (v instanceof LocalDateTime ldt) { + return Timestamp.valueOf(ldt); + } + return Timestamp.valueOf(v.toString()); + } + + /** + * 时间类型兼容转换为 java.util.Date(Bo 字段类型) + */ + private Date toDate(Object v) { + Timestamp ts = toTimestamp(v); + return ts == null ? null : new Date(ts.getTime()); + } } diff --git a/zdxt-modules/zdxt-enforcement-code/src/main/resources/mapper/enforcementcode/XzjcInfoSyncMapper.xml b/zdxt-modules/zdxt-enforcement-code/src/main/resources/mapper/enforcementcode/XzjcInfoSyncMapper.xml new file mode 100644 index 00000000..bfc265e5 --- /dev/null +++ b/zdxt-modules/zdxt-enforcement-code/src/main/resources/mapper/enforcementcode/XzjcInfoSyncMapper.xml @@ -0,0 +1,89 @@ + + + + + + + + + + + + + INSERT INTO SZSFJ_ZFJDM_XZJC_INFO + (YWID, BJQYMC, BJQYTYSHXYDM, JCSX, RQSJ, ZFYJ, JCLB, JCYY, + SFLHJC, LHJCBH, SFWTJC, WTJCBMMC, QTYYXXQ, + ZFRYXM, XZZFZH, QTZFRYXM, QTXZZFZH, ZFDWMC, ZFBMMC, YWCJSJ, YWXGSJ) + VALUES + + (#{item.ywid}, #{item.bjqymc}, #{item.bjqytyshxydm}, #{item.jcsx}, #{item.rqsj}, + #{item.zfyj}, #{item.jclb}, #{item.jcyy}, #{item.sflhjc}, #{item.lhjcbh}, + #{item.sfwtjc}, #{item.wtjcbmmc}, #{item.qtyyxxq}, + #{item.zfryxm}, #{item.xzzfzh}, #{item.qtzfryxm}, #{item.qtxzzfzh}, + #{item.zfdwmc}, #{item.zfbmmc}, #{item.ywcjsj}, #{item.ywxgsj}) + + ON DUPLICATE KEY UPDATE + BJQYMC = VALUES(BJQYMC), + BJQYTYSHXYDM = VALUES(BJQYTYSHXYDM), + JCSX = VALUES(JCSX), + RQSJ = VALUES(RQSJ), + ZFYJ = VALUES(ZFYJ), + JCLB = VALUES(JCLB), + JCYY = VALUES(JCYY), + SFLHJC = VALUES(SFLHJC), + LHJCBH = VALUES(LHJCBH), + SFWTJC = VALUES(SFWTJC), + WTJCBMMC = VALUES(WTJCBMMC), + QTYYXXQ = VALUES(QTYYXXQ), + ZFRYXM = VALUES(ZFRYXM), + XZZFZH = VALUES(XZZFZH), + QTZFRYXM = VALUES(QTZFRYXM), + QTXZZFZH = VALUES(QTXZZFZH), + ZFDWMC = VALUES(ZFDWMC), + ZFBMMC = VALUES(ZFBMMC), + YWCJSJ = VALUES(YWCJSJ), + YWXGSJ = VALUES(YWXGSJ) + + diff --git a/zdxt-web-server/zdxt-admin-web-server/src/test/java/com/zdxt/service/test/XzjcInfoSyncTest.java b/zdxt-web-server/zdxt-admin-web-server/src/test/java/com/zdxt/service/test/XzjcInfoSyncTest.java index e269ec1f..e54f6856 100644 --- a/zdxt-web-server/zdxt-admin-web-server/src/test/java/com/zdxt/service/test/XzjcInfoSyncTest.java +++ b/zdxt-web-server/zdxt-admin-web-server/src/test/java/com/zdxt/service/test/XzjcInfoSyncTest.java @@ -9,6 +9,8 @@ import org.mockito.ArgumentMatchers; import org.mockito.InjectMocks; import org.mockito.Mock; import org.mockito.junit.jupiter.MockitoExtension; +import org.redisson.api.RLock; +import org.redisson.api.RedissonClient; import org.springframework.jdbc.core.JdbcTemplate; import java.sql.Timestamp; @@ -16,6 +18,7 @@ import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; +import java.util.concurrent.TimeUnit; import static org.junit.jupiter.api.Assertions.*; import static org.mockito.ArgumentMatchers.*; @@ -36,6 +39,12 @@ class XzjcInfoSyncTest { @Mock private JdbcTemplate jdbcTemplate; + @Mock + private RedissonClient redissonClient; + + @Mock + private RLock lock; + @InjectMocks private XzjcInfoSyncServiceImpl syncService; @@ -57,7 +66,10 @@ class XzjcInfoSyncTest { @Test @DisplayName("目标表为空时水位为 null,触发全量查询") - void testFullScanWhenTargetTableEmpty() { + void testFullScanWhenTargetTableEmpty() throws Exception { + when(redissonClient.getLock(anyString())).thenReturn(lock); + when(lock.tryLock(anyLong(), anyLong(), any(TimeUnit.class))).thenReturn(true); + when(lock.isHeldByCurrentThread()).thenReturn(true); when(jdbcTemplate.queryForList(anyString())).thenReturn(new ArrayList<>()); when(jdbcTemplate.queryForList(anyString(), any(Object[].class))) .thenReturn(List.of(row("1", "全量企业"))); @@ -67,15 +79,30 @@ class XzjcInfoSyncTest { int count = syncService.syncIncremental(); assertEquals(1, count); + verify(lock).unlock(); ArgumentCaptor argsCaptor = ArgumentCaptor.forClass(Object[].class); verify(jdbcTemplate).queryForList(anyString(), argsCaptor.capture()); Object[] args = argsCaptor.getValue(); - assertEquals(2, args.length, "增量查询应传 2 个水位参数"); + assertEquals(6, args.length, "键集分页查询应传 6 个游标参数(时间x3、id x2、分页大小)"); assertNull(args[0], "目标表为空时水位应为 null"); - assertNull(args[1], "目标表为空时水位应为 null"); + assertNull(args[3], "目标表为空时游标 id 应为 null"); + assertEquals(500, args[5], "分页大小应为 PAGE_SIZE=500"); } -// -// // ======================== 同步主流程 ======================== + + @Test + @DisplayName("未获取到分布式锁时直接返回 0 且不查询数据库") + void testSkipWhenLockNotAcquired() throws Exception { + when(redissonClient.getLock(anyString())).thenReturn(lock); + when(lock.tryLock(anyLong(), anyLong(), any(TimeUnit.class))).thenReturn(false); + + int count = syncService.syncIncremental(); + + assertEquals(0, count, "未获取到锁时应返回 0"); + verify(jdbcTemplate, never()).queryForList(anyString()); + verify(lock, never()).unlock(); + } + + // ======================== 同步主流程 ======================== // // @Test // @DisplayName("有增量数据时正常批量 upsert 并返回处理条数") From 08d5d6eb6990bdc07f3d2a290d78616654f64273 Mon Sep 17 00:00:00 2001 From: vincent Date: Thu, 22 Oct 2026 16:02:59 +0800 Subject: [PATCH 4/8] =?UTF-8?q?=E4=BF=AE=E6=94=B9=E4=BA=86=E9=85=8D?= =?UTF-8?q?=E7=BD=AE=E9=A1=B9=E7=9B=AE?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../service/impl/SysJobServiceImpl.java | 1 + .../src/main/resources/application-dev.yml | 80 +++++++++---------- 2 files changed, 39 insertions(+), 42 deletions(-) diff --git a/zdxt-modules/zdxt-system/src/main/java/org/dromara/system/service/impl/SysJobServiceImpl.java b/zdxt-modules/zdxt-system/src/main/java/org/dromara/system/service/impl/SysJobServiceImpl.java index 30fa5b15..d6e01bde 100644 --- a/zdxt-modules/zdxt-system/src/main/java/org/dromara/system/service/impl/SysJobServiceImpl.java +++ b/zdxt-modules/zdxt-system/src/main/java/org/dromara/system/service/impl/SysJobServiceImpl.java @@ -51,6 +51,7 @@ public class SysJobServiceImpl implements ISysJobService { for (SysJob job : jobList) { ScheduleUtils.createScheduleJob(scheduler, job); } + scheduler.start(); // } /** diff --git a/zdxt-web-server/zdxt-admin-web-server/src/main/resources/application-dev.yml b/zdxt-web-server/zdxt-admin-web-server/src/main/resources/application-dev.yml index 9cbadd33..3c03c5d5 100644 --- a/zdxt-web-server/zdxt-admin-web-server/src/main/resources/application-dev.yml +++ b/zdxt-web-server/zdxt-admin-web-server/src/main/resources/application-dev.yml @@ -1,9 +1,9 @@ zdxt: file: # Windows/Linux 本地开发均可用;生产环境在 application-prod.yml 覆盖 -# upload-path: D:\zfjdm\uploadPath + # upload-path: D:\zfjdm\uploadPath upload-path: /usr/local/uploadPath -# upload-path: /Users/vincent/uploadPath + # upload-path: /Users/vincent/uploadPath url-prefix: /profile qr_code_url: /usr/local/uploads/zfjd_logo.png demo_enabled: false @@ -57,42 +57,42 @@ spring: datasource: # 主库数据源 master: - driverClassName: com.mysql.cj.jdbc.Driver - url: jdbc:mysql://146.56.223.227:3306/zfjd2.0?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8 - username: zfjd - password: zdxt@1234 -# url: jdbc:mysql://172.16.20.72:3306/zfjd_ef20_1_2026_07_13?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8 -# username: root -# password: zdxt@8888 + # driverClassName: com.mysql.cj.jdbc.Driver + # url: jdbc:mysql://146.56.223.227:3306/zfjd2.0?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8 + # username: zfjd + # password: zdxt@1234 + url: jdbc:mysql://172.16.20.72:3306/zfjd_ef20_1_2026_07_13?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8 + username: root + password: zdxt@8888 # jdbc 所有参数配置参考 https://lionli.blog.csdn.net/article/details/122018562 # rewriteBatchedStatements=true 批处理优化 大幅提升批量插入更新删除性能(对数据库有性能损耗 使用批量操作应考虑性能问题) -# # 从库数据源 -# slave: -# lazy: true -# type: ${spring.datasource.type} -# driverClassName: com.mysql.cj.jdbc.Driver -# url: jdbc:mysql://localhost:3306/ry-vue?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8&autoReconnect=true&rewriteBatchedStatements=true&allowPublicKeyRetrieval=true&nullCatalogMeansCurrent=true -# username: -# password: -# oracle: -# type: ${spring.datasource.type} -# driverClassName: oracle.jdbc.OracleDriver -# url: jdbc:oracle:thin:@//localhost:1521/XE -# username: ROOT -# password: root -# postgres: -# type: ${spring.datasource.type} -# driverClassName: org.postgresql.Driver -# url: jdbc:postgresql://localhost:5432/postgres?useUnicode=true&characterEncoding=utf8&useSSL=true&autoReconnect=true&reWriteBatchedInserts=true -# username: root -# password: root -# sqlserver: -# type: ${spring.datasource.type} -# driverClassName: com.microsoft.sqlserver.jdbc.SQLServerDriver -# url: jdbc:sqlserver://localhost:1433;DatabaseName=tempdb;SelectMethod=cursor;encrypt=false;rewriteBatchedStatements=true -# username: SA -# password: root + # # 从库数据源 + # slave: + # lazy: true + # type: ${spring.datasource.type} + # driverClassName: com.mysql.cj.jdbc.Driver + # url: jdbc:mysql://localhost:3306/ry-vue?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8&autoReconnect=true&rewriteBatchedStatements=true&allowPublicKeyRetrieval=true&nullCatalogMeansCurrent=true + # username: + # password: + # oracle: + # type: ${spring.datasource.type} + # driverClassName: oracle.jdbc.OracleDriver + # url: jdbc:oracle:thin:@//localhost:1521/XE + # username: ROOT + # password: root + # postgres: + # type: ${spring.datasource.type} + # driverClassName: org.postgresql.Driver + # url: jdbc:postgresql://localhost:5432/postgres?useUnicode=true&characterEncoding=utf8&useSSL=true&autoReconnect=true&reWriteBatchedInserts=true + # username: root + # password: root + # sqlserver: + # type: ${spring.datasource.type} + # driverClassName: com.microsoft.sqlserver.jdbc.SQLServerDriver + # url: jdbc:sqlserver://localhost:1433;DatabaseName=tempdb;SelectMethod=cursor;encrypt=false;rewriteBatchedStatements=true + # username: SA + # password: root hikari: # 最大连接池数量 maxPoolSize: 20 @@ -112,12 +112,8 @@ spring: --- # redis 单机配置(单机与集群只能开启一个另一个需要注释掉) spring.data: redis: -#本地环境 -# host: 172.16.20.72 -# password: - # 联调环境 - host: 146.56.223.227 - password: zdxt@123 + # 地址 + host: 172.16.20.72 # 端口,默认为6379 port: 6379 # 数据库索引 @@ -293,7 +289,7 @@ siq: #正式 # siqUrl: http://10.76.108.3/siqApi # code: zfjdm -# secretKey: SXRpWEhVN3RHM3ZFbzRQcQ== + # secretKey: SXRpWEhVN3RHM3ZFbzRQcQ== #测试 siqUrl: https://egbpub.siqhz.com/egb/api/thirdauth siqBaseUrl: https://egbpub.siqhz.com From 192247cdf6243f51a8a7b71da7429073cc2ca9f7 Mon Sep 17 00:00:00 2001 From: vincent Date: Thu, 22 Oct 2026 17:22:55 +0800 Subject: [PATCH 5/8] =?UTF-8?q?=E6=95=B0=E6=8D=AE=E7=BC=96=E7=A0=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../com/zdxt/enforcementcode/domain/bo/XzjcInfoSyncBo.java | 6 ++++++ .../service/impl/XzjcInfoSyncServiceImpl.java | 2 ++ .../mapper/enforcementcode/XzjcInfoSyncMapper.xml | 7 +++++-- 3 files changed, 13 insertions(+), 2 deletions(-) diff --git a/zdxt-modules/zdxt-enforcement-code/src/main/java/com/zdxt/enforcementcode/domain/bo/XzjcInfoSyncBo.java b/zdxt-modules/zdxt-enforcement-code/src/main/java/com/zdxt/enforcementcode/domain/bo/XzjcInfoSyncBo.java index 8f138fc1..bb4b22ab 100644 --- a/zdxt-modules/zdxt-enforcement-code/src/main/java/com/zdxt/enforcementcode/domain/bo/XzjcInfoSyncBo.java +++ b/zdxt-modules/zdxt-enforcement-code/src/main/java/com/zdxt/enforcementcode/domain/bo/XzjcInfoSyncBo.java @@ -48,6 +48,12 @@ public class XzjcInfoSyncBo { /** 委托检查部门名称(WTJCBMMC) */ private String wtjcbmmc; + /** 是否扫码:0是,1否(SFSM) */ + private Integer sfsm; + + /** 未扫码原因:0其他|1企业原因|2系统原因|3扫码未能显示企业信息|9补录(WSMYY) */ + private String wsmyy; + /** 其他原因详情(QTYYXXQ) */ private String qtyyxxq; diff --git a/zdxt-modules/zdxt-enforcement-code/src/main/java/com/zdxt/enforcementcode/service/impl/XzjcInfoSyncServiceImpl.java b/zdxt-modules/zdxt-enforcement-code/src/main/java/com/zdxt/enforcementcode/service/impl/XzjcInfoSyncServiceImpl.java index 33b87394..b1c8ac4c 100644 --- a/zdxt-modules/zdxt-enforcement-code/src/main/java/com/zdxt/enforcementcode/service/impl/XzjcInfoSyncServiceImpl.java +++ b/zdxt-modules/zdxt-enforcement-code/src/main/java/com/zdxt/enforcementcode/service/impl/XzjcInfoSyncServiceImpl.java @@ -163,6 +163,8 @@ public class XzjcInfoSyncServiceImpl implements IXzjcInfoSyncService { bo.setLhjcbh(fit(unionNo, 50)); bo.setSfwtjc(hasAuto != null && hasAuto == 1 ? 1 : 0); bo.setWtjcbmmc(fit(row.get("entrust_dept_name"), 128)); + bo.setSfsm(toLong(row.get("enforce")) == null ? null : toLong(row.get("enforce")).intValue()); + bo.setWsmyy(fit(row.get("check_css"), 256)); bo.setQtyyxxq(fit(row.get("other_reasons"), 512)); bo.setZfryxm(fit(row.get("law_enforcer"), 64)); bo.setXzzfzh(fit(row.get("law_enforcer_id"), 64)); diff --git a/zdxt-modules/zdxt-enforcement-code/src/main/resources/mapper/enforcementcode/XzjcInfoSyncMapper.xml b/zdxt-modules/zdxt-enforcement-code/src/main/resources/mapper/enforcementcode/XzjcInfoSyncMapper.xml index bfc265e5..86865cb0 100644 --- a/zdxt-modules/zdxt-enforcement-code/src/main/resources/mapper/enforcementcode/XzjcInfoSyncMapper.xml +++ b/zdxt-modules/zdxt-enforcement-code/src/main/resources/mapper/enforcementcode/XzjcInfoSyncMapper.xml @@ -27,6 +27,7 @@ law_enforcer, law_enforcer_id, law_enforcer_two, law_enforcer_id_two, bureau_dept_name, law_enforcement, + enforce, check_css, create_time, update_time FROM enforcement_registration WHERE is_delete = 0 @@ -54,13 +55,13 @@ INSERT INTO SZSFJ_ZFJDM_XZJC_INFO (YWID, BJQYMC, BJQYTYSHXYDM, JCSX, RQSJ, ZFYJ, JCLB, JCYY, - SFLHJC, LHJCBH, SFWTJC, WTJCBMMC, QTYYXXQ, + SFLHJC, LHJCBH, SFWTJC, WTJCBMMC, SFSM, WSMYY, QTYYXXQ, ZFRYXM, XZZFZH, QTZFRYXM, QTXZZFZH, ZFDWMC, ZFBMMC, YWCJSJ, YWXGSJ) VALUES (#{item.ywid}, #{item.bjqymc}, #{item.bjqytyshxydm}, #{item.jcsx}, #{item.rqsj}, #{item.zfyj}, #{item.jclb}, #{item.jcyy}, #{item.sflhjc}, #{item.lhjcbh}, - #{item.sfwtjc}, #{item.wtjcbmmc}, #{item.qtyyxxq}, + #{item.sfwtjc}, #{item.wtjcbmmc}, #{item.sfsm}, #{item.wsmyy}, #{item.qtyyxxq}, #{item.zfryxm}, #{item.xzzfzh}, #{item.qtzfryxm}, #{item.qtxzzfzh}, #{item.zfdwmc}, #{item.zfbmmc}, #{item.ywcjsj}, #{item.ywxgsj}) @@ -76,6 +77,8 @@ LHJCBH = VALUES(LHJCBH), SFWTJC = VALUES(SFWTJC), WTJCBMMC = VALUES(WTJCBMMC), + SFSM = VALUES(SFSM), + WSMYY = VALUES(WSMYY), QTYYXXQ = VALUES(QTYYXXQ), ZFRYXM = VALUES(ZFRYXM), XZZFZH = VALUES(XZZFZH), From 0d5b475f453b5a7c21bd3800f2bc2af8b5b51b8d Mon Sep 17 00:00:00 2001 From: vincent Date: Wed, 28 Oct 2026 16:24:02 +0800 Subject: [PATCH 6/8] =?UTF-8?q?=E7=BC=96=E7=A0=81=E5=8A=9F=E8=83=BD?= =?UTF-8?q?=E4=BC=98=E5=8C=96?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- script/sql/vincent/V1.10.1_20261013.sql | 54 +++++-------------- script/sql/vincent/V1.10.1_20261013_tgk.sql | 34 ++++++++++++ .../mapper/XzjcInfoSyncMapper.java | 19 ++----- .../mapper/XzjcInfoSyncTgkMapper.java | 34 ++++++++++++ .../quartz/job/XzjcInfoSyncJob.java | 2 +- .../service/impl/XzjcInfoSyncServiceImpl.java | 47 +++++++++------- .../enforcementcode/XzjcInfoSyncMapper.xml | 44 --------------- .../enforcementcode/XzjcInfoSyncTgkMapper.xml | 53 ++++++++++++++++++ .../src/main/resources/application-dev.yml | 39 +++----------- .../src/main/resources/application-prod.yml | 8 +++ 10 files changed, 180 insertions(+), 154 deletions(-) create mode 100644 script/sql/vincent/V1.10.1_20261013_tgk.sql create mode 100644 zdxt-modules/zdxt-enforcement-code/src/main/java/com/zdxt/enforcementcode/mapper/XzjcInfoSyncTgkMapper.java create mode 100644 zdxt-modules/zdxt-enforcement-code/src/main/resources/mapper/enforcementcode/XzjcInfoSyncTgkMapper.xml diff --git a/script/sql/vincent/V1.10.1_20261013.sql b/script/sql/vincent/V1.10.1_20261013.sql index ea6fe0e3..20fd8dfc 100644 --- a/script/sql/vincent/V1.10.1_20261013.sql +++ b/script/sql/vincent/V1.10.1_20261013.sql @@ -1,46 +1,18 @@ -CREATE TABLE `SZSFJ_ZFJDM_XZJC_INFO` ( - `ID` bigint NOT NULL AUTO_INCREMENT COMMENT '主键,自增ID', - `YWID` varchar(64) NOT NULL COMMENT '业务ID', - `BJQYMC` varchar(128) DEFAULT NULL COMMENT '被检查企业名称', - `BJQYTYSHXYDM` varchar(32) DEFAULT NULL COMMENT '被检查企业统一社会信用代码', - `JCSX` varchar(512) DEFAULT NULL COMMENT '检查事项', - `RQSJ` datetime DEFAULT NULL COMMENT '入企时间', - `ZFYJ` varchar(512) DEFAULT NULL COMMENT '执法依据', - `JCLB` varchar(2) DEFAULT NULL COMMENT '检查类别:1行政检查|2行政处罚|3行政许可|4行政强制|5行政征收|6行政给付|7行政确认|8行政登记|9行政裁决|10文书送达', - `JCYY` varchar(2) DEFAULT NULL COMMENT '检查原因:01日常检查|02投诉举报|03上级交办|04部门移送|05重点领域治理部署|06专项行动|09其它', - `SFLHJC` tinyint DEFAULT NULL COMMENT '是否联合检查:0否,1是', - `LHJCBH` varchar(50) DEFAULT NULL COMMENT '联合检查编号', - `SFWTJC` tinyint DEFAULT NULL COMMENT '是否委托检查:0否,1是', - `WTJCBMMC` varchar(128) DEFAULT NULL COMMENT '委托检查部门名称', - `SFSM` tinyint DEFAULT NULL COMMENT '是否扫码:0是,1否', - `WSMYY` varchar(256) DEFAULT NULL COMMENT '未扫码原因:0其他|1企业原因|2系统原因|3扫码未能显示企业信息|9补录', - `QTYYXXQ` varchar(512) DEFAULT NULL COMMENT '其他原因详情', - `ZFRYXM` varchar(64) DEFAULT NULL COMMENT '执法人员姓名', - `XZZFZH` varchar(64) DEFAULT NULL COMMENT '行政执法证号', - `QTZFRYXM` varchar(64) DEFAULT NULL COMMENT '其他执法人员姓名', - `QTXZZFZH` varchar(64) DEFAULT NULL COMMENT '其他行政执法证号', - `ZFDWMC` varchar(64) DEFAULT NULL COMMENT '执法单位名称', - `ZFBMMC` varchar(64) DEFAULT NULL COMMENT '执法部门名称', - `YWCJSJ` datetime DEFAULT NULL COMMENT '业务创建时间', - `YWXGSJ` datetime DEFAULT NULL COMMENT '业务修改时间', - `CJSJ` datetime DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间', - `XGSJ` datetime DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '修改时间', - PRIMARY KEY (`ID`), - UNIQUE KEY `uk_ywid` (`YWID`), - KEY `idx_bjqy_credit` (`BJQYTYSHXYDM`), - KEY `idx_rqsj` (`RQSJ`) -) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='行政检查信息表'; --- 定时任务:每天凌晨2点同步 enforcement_registration 增量数据到 SZSFJ_ZFJDM_XZJC_INFO -INSERT INTO sys_job (job_name, job_group, invoke_target, cron_expression, misfire_policy, concurrent, status, create_by, - create_time, remark) -VALUES ('行政检查信息增量同步', +INSERT INTO sys_job (job_name, job_group, invoke_target, cron_expression, + misfire_policy, concurrent, status, create_by, create_time, remark) +VALUES ('省数据编目-行政检查信息同步到前置库', 'DEFAULT', 'xzjcInfoSyncJob.execute()', '0 0 2 * * ?', - '3', - '1', - '0', - 'admin', - NOW(), + '3', -- misfire: 放弃错过的执行 + '1', -- concurrent: 禁止并发 + '0', -- status: 正常 + 'admin', NOW(), '每天凌晨2点将enforcement_registration增量数据同步到SZSFJ_ZFJDM_XZJC_INFO表(市司法局数据共享)'); + +ALTER TABLE enforcement_registration + MODIFY COLUMN update_time DATETIME DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间'; + + +update enforcement_registration set update_time = create_time where update_time is null; diff --git a/script/sql/vincent/V1.10.1_20261013_tgk.sql b/script/sql/vincent/V1.10.1_20261013_tgk.sql new file mode 100644 index 00000000..4cd7a9fd --- /dev/null +++ b/script/sql/vincent/V1.10.1_20261013_tgk.sql @@ -0,0 +1,34 @@ +DROP TABLE IF EXISTS `SZSFJ_ZFJDM_XZJC_INFO`; +CREATE TABLE `SZSFJ_ZFJDM_XZJC_INFO` ( + `ID` bigint NOT NULL AUTO_INCREMENT COMMENT '主键,自增ID', + `YWID` varchar(64) NOT NULL COMMENT '业务ID', + `BJQYMC` varchar(128) DEFAULT NULL COMMENT '被检查企业名称', + `BJQYTYSHXYDM` varchar(32) DEFAULT NULL COMMENT '被检查企业统一社会信用代码', + `JCSX` varchar(512) DEFAULT NULL COMMENT '检查事项', + `RQSJ` datetime DEFAULT NULL COMMENT '入企时间', + `ZFYJ` varchar(512) DEFAULT NULL COMMENT '执法依据', + `JCLB` varchar(2) DEFAULT NULL COMMENT '检查类别:1行政检查|2行政处罚|3行政许可|4行政强制|5行政征收|6行政给付|7行政确认|8行政登记|9行政裁决|10文书送达', + `JCYY` varchar(2) DEFAULT NULL COMMENT '检查原因:01日常检查|02投诉举报|03上级交办|04部门移送|05重点领域治理部署|06专项行动|09其它', + `SFLHJC` tinyint DEFAULT NULL COMMENT '是否联合检查:0否,1是', + `LHJCBH` varchar(50) DEFAULT NULL COMMENT '联合检查编号', + `SFWTJC` tinyint DEFAULT NULL COMMENT '是否委托检查:0否,1是', + `WTJCBMMC` varchar(128) DEFAULT NULL COMMENT '委托检查部门名称', + `SFSM` tinyint DEFAULT NULL COMMENT '是否扫码:0是,1否', + `WSMYY` varchar(256) DEFAULT NULL COMMENT '未扫码原因:0其他|1企业原因|2系统原因|3扫码未能显示企业信息|9补录', + `QTYYXXQ` varchar(512) DEFAULT NULL COMMENT '其他原因详情', + `ZFRYXM` varchar(64) DEFAULT NULL COMMENT '执法人员姓名', + `XZZFZH` varchar(64) DEFAULT NULL COMMENT '行政执法证号', + `QTZFRYXM` varchar(64) DEFAULT NULL COMMENT '其他执法人员姓名', + `QTXZZFZH` varchar(64) DEFAULT NULL COMMENT '其他行政执法证号', + `ZFDWMC` varchar(64) DEFAULT NULL COMMENT '执法单位名称', + `ZFBMMC` varchar(64) DEFAULT NULL COMMENT '执法部门名称', + `YWCJSJ` datetime DEFAULT NULL COMMENT '业务创建时间', + `YWXGSJ` datetime DEFAULT NULL COMMENT '业务修改时间', + `CJSJ` datetime DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间', + `XGSJ` datetime DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '修改时间', + `ZLBS` varchar(2) DEFAULT '0' COMMENT '增量标识,0|未同步,1|已同步', + PRIMARY KEY (`ID`), + UNIQUE KEY `uk_ywid` (`YWID`), + KEY `idx_bjqy_credit` (`BJQYTYSHXYDM`), + KEY `idx_rqsj` (`RQSJ`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='行政检查信息表'; diff --git a/zdxt-modules/zdxt-enforcement-code/src/main/java/com/zdxt/enforcementcode/mapper/XzjcInfoSyncMapper.java b/zdxt-modules/zdxt-enforcement-code/src/main/java/com/zdxt/enforcementcode/mapper/XzjcInfoSyncMapper.java index 6769824a..d2621c11 100644 --- a/zdxt-modules/zdxt-enforcement-code/src/main/java/com/zdxt/enforcementcode/mapper/XzjcInfoSyncMapper.java +++ b/zdxt-modules/zdxt-enforcement-code/src/main/java/com/zdxt/enforcementcode/mapper/XzjcInfoSyncMapper.java @@ -1,6 +1,5 @@ package com.zdxt.enforcementcode.mapper; -import com.zdxt.enforcementcode.domain.bo.XzjcInfoSyncBo; import org.apache.ibatis.annotations.Param; import java.util.Date; @@ -8,19 +7,14 @@ import java.util.List; import java.util.Map; /** - * 行政检查信息同步 Mapper 接口 - *

增量同步 enforcement_registration -> SZSFJ_ZFJDM_XZJC_INFO(市司法局数据共享表)

+ * 行政检查信息同步 Mapper 接口(主库) + *

仅承载源表 enforcement_registration 的增量分页读取(走默认 master 数据源)

+ *

目标表 zfjd_tgk.SZSFJ_ZFJDM_XZJC_INFO 的水位查询与写入见 {@link XzjcInfoSyncTgkMapper}

* * @author zdxt */ public interface XzjcInfoSyncMapper { - /** - * 查询增量水位:目标表已同步数据的最大业务修改时间(MAX(YWXGSJ)) - * - * @return 水位时间;目标表为空时返回 null - */ - Date selectWatermark(); /** * 按 (update_time, id) 键集分页查询源表增量数据 @@ -36,11 +30,4 @@ public interface XzjcInfoSyncMapper { @Param("endTime") Date endTime, @Param("pageSize") int pageSize); - /** - * 批量 upsert 目标表(基于 uk_ywid 唯一键 INSERT ... ON DUPLICATE KEY UPDATE,幂等) - * - * @param list 写入行集合 - * @return 影响行数(MySQL upsert 语义,不代表真实写入条数) - */ - int upsertBatch(@Param("list") List list); } diff --git a/zdxt-modules/zdxt-enforcement-code/src/main/java/com/zdxt/enforcementcode/mapper/XzjcInfoSyncTgkMapper.java b/zdxt-modules/zdxt-enforcement-code/src/main/java/com/zdxt/enforcementcode/mapper/XzjcInfoSyncTgkMapper.java new file mode 100644 index 00000000..c32f1db5 --- /dev/null +++ b/zdxt-modules/zdxt-enforcement-code/src/main/java/com/zdxt/enforcementcode/mapper/XzjcInfoSyncTgkMapper.java @@ -0,0 +1,34 @@ +package com.zdxt.enforcementcode.mapper; + +import com.baomidou.dynamic.datasource.annotation.DS; +import com.zdxt.enforcementcode.domain.bo.XzjcInfoSyncBo; +import org.apache.ibatis.annotations.Param; + +import java.util.Date; +import java.util.List; + +/** + * 行政检查信息同步 Mapper 接口(zfjd_tgk 推管库) + *

增量同步 enforcement_registration -> zfjd_tgk.SZSFJ_ZFJDM_XZJC_INFO(市司法局数据共享表)

+ *

仅承载目标表操作(水位查询/批量写入);源表分页读取见 {@link XzjcInfoSyncMapper}

+ * + * @author zdxt + */ +@DS("tgk") +public interface XzjcInfoSyncTgkMapper { + + /** + * 查询增量水位:目标表已同步数据的最大业务修改时间(MAX(YWXGSJ)) + * + * @return 水位时间;目标表为空时返回 null + */ + Date selectWatermark(); + + /** + * 批量 upsert 目标表(基于 uk_ywid 唯一键 INSERT ... ON DUPLICATE KEY UPDATE,幂等) + * + * @param list 写入行集合 + * @return 影响行数(MySQL upsert 语义,不代表真实写入条数) + */ + int upsertBatch(@Param("list") List list); +} diff --git a/zdxt-modules/zdxt-enforcement-code/src/main/java/com/zdxt/enforcementcode/quartz/job/XzjcInfoSyncJob.java b/zdxt-modules/zdxt-enforcement-code/src/main/java/com/zdxt/enforcementcode/quartz/job/XzjcInfoSyncJob.java index 9f5c3806..6ebe5974 100644 --- a/zdxt-modules/zdxt-enforcement-code/src/main/java/com/zdxt/enforcementcode/quartz/job/XzjcInfoSyncJob.java +++ b/zdxt-modules/zdxt-enforcement-code/src/main/java/com/zdxt/enforcementcode/quartz/job/XzjcInfoSyncJob.java @@ -7,7 +7,7 @@ import org.springframework.stereotype.Component; /** * 行政检查信息同步定时任务 - *

每天将 enforcement_registration 增量数据同步到 SZSFJ_ZFJDM_XZJC_INFO(市司法局数据共享表)

+ *

每天将 enforcement_registration 增量数据同步到 zfjd_tgk 库的 SZSFJ_ZFJDM_XZJC_INFO(市司法局数据共享表)

*

默认 cron: 0 0 2 * * ?(每天凌晨 2 点)

* * @author zdxt diff --git a/zdxt-modules/zdxt-enforcement-code/src/main/java/com/zdxt/enforcementcode/service/impl/XzjcInfoSyncServiceImpl.java b/zdxt-modules/zdxt-enforcement-code/src/main/java/com/zdxt/enforcementcode/service/impl/XzjcInfoSyncServiceImpl.java index b1c8ac4c..1548d316 100644 --- a/zdxt-modules/zdxt-enforcement-code/src/main/java/com/zdxt/enforcementcode/service/impl/XzjcInfoSyncServiceImpl.java +++ b/zdxt-modules/zdxt-enforcement-code/src/main/java/com/zdxt/enforcementcode/service/impl/XzjcInfoSyncServiceImpl.java @@ -3,6 +3,7 @@ package com.zdxt.enforcementcode.service.impl; import com.zdxt.enforcementcode.domain.bo.XzjcInfoSyncBo; import com.zdxt.enforcementcode.mapper.XzjcInfoSyncMapper; +import com.zdxt.enforcementcode.mapper.XzjcInfoSyncTgkMapper; import com.zdxt.enforcementcode.service.IXzjcInfoSyncService; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; @@ -20,13 +21,9 @@ import java.util.Map; import java.util.concurrent.TimeUnit; /** - * 行政检查信息同步服务 - *

增量同步 enforcement_registration -> SZSFJ_ZFJDM_XZJC_INFO(市司法局数据共享表)

- *

增量水位:目标表 MAX(YWXGSJ),源表 update_time >= 水位即为增量;目标表为空时首次自动全量

- *

写入策略:基于 uk_ywid 唯一键 INSERT ... ON DUPLICATE KEY UPDATE(幂等)

- *

读取策略:(update_time, id) 键集分页,单页单批,避免一次性加载全量数据导致内存溢出

- *

并发控制:Redisson 分布式锁,覆盖 Quartz 调度重叠、手动触发及多实例部署场景

- *

SQL 定义见 mapper/enforcementcode/XzjcInfoSyncMapper.xml

+ * 行政检查信息增量同步服务实现 + *

源表:master.enforcement_registration;目标表:zfjd_tgk.SZSFJ_ZFJDM_XZJC_INFO(推管库,经 @DS("tgk") 数据源写入)

+ *

SQL 定义见 mapper/enforcementcode/XzjcInfoSyncMapper.xml 与 XzjcInfoSyncTgkMapper.xml

* * @author zdxt */ @@ -44,8 +41,12 @@ public class XzjcInfoSyncServiceImpl implements IXzjcInfoSyncService { /** 同步分布式锁 key */ private static final String LOCK_KEY = "xzjc_info_sync:lock"; + /** 源表读取(master) */ private final XzjcInfoSyncMapper xzjcInfoSyncMapper; + /** 目标表写入与水位查询(zfjd_tgk) */ + private final XzjcInfoSyncTgkMapper xzjcInfoSyncTgkMapper; + private final RedissonClient redissonClient; /** @@ -82,7 +83,7 @@ public class XzjcInfoSyncServiceImpl implements IXzjcInfoSyncService { private int doSync() { // 数据截止时间:今天零点(即只同步前一天晚上 23:59:59 及更早的数据),避免同步当日仍在变化的数据 Date endTime = Timestamp.valueOf(LocalDate.now().atStartOfDay()); - Date watermark = xzjcInfoSyncMapper.selectWatermark(); + Date watermark = xzjcInfoSyncTgkMapper.selectWatermark(); Date cursorTime = watermark; String cursorId = null; int total = 0; @@ -118,7 +119,7 @@ public class XzjcInfoSyncServiceImpl implements IXzjcInfoSyncService { if (limitReached) { log.warn("[XzjcInfoSync] 达到单次最大分页数 {}(约 {} 条), 剩余数据下次任务继续同步", MAX_PAGES, (long) MAX_PAGES * PAGE_SIZE); } - log.info("[XzjcInfoSync] 增量同步完成: 共处理 {} 条, 起始水位={}, 截止={}", total, watermark, endTime); + log.info("[XzjcInfoSync] 增量同步完成(zfjd_tgk): 共处理 {} 条, 起始水位={}, 截止={}", total, watermark, endTime); return total; } @@ -126,16 +127,24 @@ public class XzjcInfoSyncServiceImpl implements IXzjcInfoSyncService { * 页级批量 upsert;整批失败时降级为逐条写入,跳过脏数据行,避免单行异常导致游标卡死 */ private void upsertSafely(List batch) { - try { - xzjcInfoSyncMapper.upsertBatch(batch); - } catch (Exception e) { - log.error("[XzjcInfoSync] 批量写入失败,降级逐条写入排查脏数据, 批次大小={}", batch.size(), e); - for (XzjcInfoSyncBo bo : batch) { - try { - xzjcInfoSyncMapper.upsertBatch(List.of(bo)); - } catch (Exception rowEx) { - log.error("[XzjcInfoSync] 脏数据跳过: ywid={}", bo.getYwid(), rowEx); - } +// try { +// xzjcInfoSyncTgkMapper.upsertBatch(batch); +// } catch (Exception e) { +// log.error("[XzjcInfoSync] 批量写入失败,降级逐条写入排查脏数据, 批次大小={}", batch.size(), e); +// for (XzjcInfoSyncBo bo : batch) { +// try { +// xzjcInfoSyncTgkMapper.upsertBatch(List.of(bo)); +// } catch (Exception rowEx) { +// log.error("[XzjcInfoSync] 脏数据跳过: ywid={}", bo.getYwid(), rowEx); +// } +// } +// } + + for (XzjcInfoSyncBo bo : batch) { + try { + xzjcInfoSyncTgkMapper.upsertBatch(List.of(bo)); + } catch (Exception rowEx) { + log.error("[XzjcInfoSync] 脏数据跳过: ywid={}", bo.getYwid(), rowEx); } } } diff --git a/zdxt-modules/zdxt-enforcement-code/src/main/resources/mapper/enforcementcode/XzjcInfoSyncMapper.xml b/zdxt-modules/zdxt-enforcement-code/src/main/resources/mapper/enforcementcode/XzjcInfoSyncMapper.xml index 86865cb0..fb4f19b2 100644 --- a/zdxt-modules/zdxt-enforcement-code/src/main/resources/mapper/enforcementcode/XzjcInfoSyncMapper.xml +++ b/zdxt-modules/zdxt-enforcement-code/src/main/resources/mapper/enforcementcode/XzjcInfoSyncMapper.xml @@ -4,12 +4,6 @@ "http://mybatis.org/dtd/mybatis-3-mapper.dtd"> - - - - - INSERT INTO SZSFJ_ZFJDM_XZJC_INFO - (YWID, BJQYMC, BJQYTYSHXYDM, JCSX, RQSJ, ZFYJ, JCLB, JCYY, - SFLHJC, LHJCBH, SFWTJC, WTJCBMMC, SFSM, WSMYY, QTYYXXQ, - ZFRYXM, XZZFZH, QTZFRYXM, QTXZZFZH, ZFDWMC, ZFBMMC, YWCJSJ, YWXGSJ) - VALUES - - (#{item.ywid}, #{item.bjqymc}, #{item.bjqytyshxydm}, #{item.jcsx}, #{item.rqsj}, - #{item.zfyj}, #{item.jclb}, #{item.jcyy}, #{item.sflhjc}, #{item.lhjcbh}, - #{item.sfwtjc}, #{item.wtjcbmmc}, #{item.sfsm}, #{item.wsmyy}, #{item.qtyyxxq}, - #{item.zfryxm}, #{item.xzzfzh}, #{item.qtzfryxm}, #{item.qtxzzfzh}, - #{item.zfdwmc}, #{item.zfbmmc}, #{item.ywcjsj}, #{item.ywxgsj}) - - ON DUPLICATE KEY UPDATE - BJQYMC = VALUES(BJQYMC), - BJQYTYSHXYDM = VALUES(BJQYTYSHXYDM), - JCSX = VALUES(JCSX), - RQSJ = VALUES(RQSJ), - ZFYJ = VALUES(ZFYJ), - JCLB = VALUES(JCLB), - JCYY = VALUES(JCYY), - SFLHJC = VALUES(SFLHJC), - LHJCBH = VALUES(LHJCBH), - SFWTJC = VALUES(SFWTJC), - WTJCBMMC = VALUES(WTJCBMMC), - SFSM = VALUES(SFSM), - WSMYY = VALUES(WSMYY), - QTYYXXQ = VALUES(QTYYXXQ), - ZFRYXM = VALUES(ZFRYXM), - XZZFZH = VALUES(XZZFZH), - QTZFRYXM = VALUES(QTZFRYXM), - QTXZZFZH = VALUES(QTXZZFZH), - ZFDWMC = VALUES(ZFDWMC), - ZFBMMC = VALUES(ZFBMMC), - YWCJSJ = VALUES(YWCJSJ), - YWXGSJ = VALUES(YWXGSJ) - diff --git a/zdxt-modules/zdxt-enforcement-code/src/main/resources/mapper/enforcementcode/XzjcInfoSyncTgkMapper.xml b/zdxt-modules/zdxt-enforcement-code/src/main/resources/mapper/enforcementcode/XzjcInfoSyncTgkMapper.xml new file mode 100644 index 00000000..229d59b6 --- /dev/null +++ b/zdxt-modules/zdxt-enforcement-code/src/main/resources/mapper/enforcementcode/XzjcInfoSyncTgkMapper.xml @@ -0,0 +1,53 @@ + + + + + + + + + + + INSERT INTO SZSFJ_ZFJDM_XZJC_INFO + (YWID, BJQYMC, BJQYTYSHXYDM, JCSX, RQSJ, ZFYJ, JCLB, JCYY, + SFLHJC, LHJCBH, SFWTJC, WTJCBMMC, SFSM, WSMYY, QTYYXXQ, + ZFRYXM, XZZFZH, QTZFRYXM, QTXZZFZH, ZFDWMC, ZFBMMC, YWCJSJ, YWXGSJ, ZLBS) + VALUES + + (#{item.ywid}, #{item.bjqymc}, #{item.bjqytyshxydm}, #{item.jcsx}, #{item.rqsj}, + #{item.zfyj}, #{item.jclb}, #{item.jcyy}, #{item.sflhjc}, #{item.lhjcbh}, + #{item.sfwtjc}, #{item.wtjcbmmc}, #{item.sfsm}, #{item.wsmyy}, #{item.qtyyxxq}, + #{item.zfryxm}, #{item.xzzfzh}, #{item.qtzfryxm}, #{item.qtxzzfzh}, + #{item.zfdwmc}, #{item.zfbmmc}, #{item.ywcjsj}, #{item.ywxgsj}, '0') + + ON DUPLICATE KEY UPDATE + BJQYMC = VALUES(BJQYMC), + BJQYTYSHXYDM = VALUES(BJQYTYSHXYDM), + JCSX = VALUES(JCSX), + RQSJ = VALUES(RQSJ), + ZFYJ = VALUES(ZFYJ), + JCLB = VALUES(JCLB), + JCYY = VALUES(JCYY), + SFLHJC = VALUES(SFLHJC), + LHJCBH = VALUES(LHJCBH), + SFWTJC = VALUES(SFWTJC), + WTJCBMMC = VALUES(WTJCBMMC), + SFSM = VALUES(SFSM), + WSMYY = VALUES(WSMYY), + QTYYXXQ = VALUES(QTYYXXQ), + ZFRYXM = VALUES(ZFRYXM), + XZZFZH = VALUES(XZZFZH), + QTZFRYXM = VALUES(QTZFRYXM), + QTXZZFZH = VALUES(QTXZZFZH), + ZFDWMC = VALUES(ZFDWMC), + ZFBMMC = VALUES(ZFBMMC), + YWCJSJ = VALUES(YWCJSJ), + YWXGSJ = VALUES(YWXGSJ), + ZLBS = '0' + + diff --git a/zdxt-web-server/zdxt-admin-web-server/src/main/resources/application-dev.yml b/zdxt-web-server/zdxt-admin-web-server/src/main/resources/application-dev.yml index 3c03c5d5..d8dfdd6f 100644 --- a/zdxt-web-server/zdxt-admin-web-server/src/main/resources/application-dev.yml +++ b/zdxt-web-server/zdxt-admin-web-server/src/main/resources/application-dev.yml @@ -57,42 +57,15 @@ spring: datasource: # 主库数据源 master: - # driverClassName: com.mysql.cj.jdbc.Driver - # url: jdbc:mysql://146.56.223.227:3306/zfjd2.0?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8 - # username: zfjd - # password: zdxt@1234 url: jdbc:mysql://172.16.20.72:3306/zfjd_ef20_1_2026_07_13?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8 username: root password: zdxt@8888 - # jdbc 所有参数配置参考 https://lionli.blog.csdn.net/article/details/122018562 - # rewriteBatchedStatements=true 批处理优化 大幅提升批量插入更新删除性能(对数据库有性能损耗 使用批量操作应考虑性能问题) - - # # 从库数据源 - # slave: - # lazy: true - # type: ${spring.datasource.type} - # driverClassName: com.mysql.cj.jdbc.Driver - # url: jdbc:mysql://localhost:3306/ry-vue?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8&autoReconnect=true&rewriteBatchedStatements=true&allowPublicKeyRetrieval=true&nullCatalogMeansCurrent=true - # username: - # password: - # oracle: - # type: ${spring.datasource.type} - # driverClassName: oracle.jdbc.OracleDriver - # url: jdbc:oracle:thin:@//localhost:1521/XE - # username: ROOT - # password: root - # postgres: - # type: ${spring.datasource.type} - # driverClassName: org.postgresql.Driver - # url: jdbc:postgresql://localhost:5432/postgres?useUnicode=true&characterEncoding=utf8&useSSL=true&autoReconnect=true&reWriteBatchedInserts=true - # username: root - # password: root - # sqlserver: - # type: ${spring.datasource.type} - # driverClassName: com.microsoft.sqlserver.jdbc.SQLServerDriver - # url: jdbc:sqlserver://localhost:1433;DatabaseName=tempdb;SelectMethod=cursor;encrypt=false;rewriteBatchedStatements=true - # username: SA - # password: root + # 推管库(行政检查信息同步目标库) + tgk: + lazy: true + url: jdbc:mysql://172.16.20.72:3306/zfjd_tgk?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8 + username: root + password: zdxt@8888 hikari: # 最大连接池数量 maxPoolSize: 20 diff --git a/zdxt-web-server/zdxt-admin-web-server/src/main/resources/application-prod.yml b/zdxt-web-server/zdxt-admin-web-server/src/main/resources/application-prod.yml index 0121d2e7..900c1359 100644 --- a/zdxt-web-server/zdxt-admin-web-server/src/main/resources/application-prod.yml +++ b/zdxt-web-server/zdxt-admin-web-server/src/main/resources/application-prod.yml @@ -52,6 +52,14 @@ spring: url: jdbc:mysql://nortdsql.cloud.sz.gov.cn:15114,nortdsql-backup.cloud.sz.gov.cn:15114/zfjd_ef20_prod?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8 username: zfjd password: szsf@zfjd + # 推管库(行政检查信息同步目标库) + tgk: + lazy: true + type: ${spring.datasource.type} + driverClassName: com.mysql.cj.jdbc.Driver + url: jdbc:mysql://nortdsql.cloud.sz.gov.cn:15114,nortdsql-backup.cloud.sz.gov.cn:15114/zfjd_tgk?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8 + username: zfjd + password: szsf@zfjd v1: lazy: true type: ${spring.datasource.type} From 792130790690992fd922f50c65025c8277c41192 Mon Sep 17 00:00:00 2001 From: vincent Date: Wed, 4 Nov 2026 11:24:11 +0800 Subject: [PATCH 7/8] =?UTF-8?q?=E4=BF=AE=E6=94=B9=E4=BA=86=E9=85=8D?= =?UTF-8?q?=E7=BD=AE=E9=A1=B9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../src/main/resources/application-dev.yml | 35 ++++--------------- .../src/main/resources/application-prod.yml | 2 +- 2 files changed, 7 insertions(+), 30 deletions(-) diff --git a/zdxt-web-server/zdxt-admin-web-server/src/main/resources/application-dev.yml b/zdxt-web-server/zdxt-admin-web-server/src/main/resources/application-dev.yml index 9bb4e40e..bb5a7466 100644 --- a/zdxt-web-server/zdxt-admin-web-server/src/main/resources/application-dev.yml +++ b/zdxt-web-server/zdxt-admin-web-server/src/main/resources/application-dev.yml @@ -64,35 +64,12 @@ spring: url: jdbc:mysql://172.16.20.72:3306/zfjd_ef20_1_2026_07_13?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8 username: root password: zdxt@8888 - # jdbc 所有参数配置参考 https://lionli.blog.csdn.net/article/details/122018562 - # rewriteBatchedStatements=true 批处理优化 大幅提升批量插入更新删除性能(对数据库有性能损耗 使用批量操作应考虑性能问题) - -# # 从库数据源 -# slave: -# lazy: true -# type: ${spring.datasource.type} -# driverClassName: com.mysql.cj.jdbc.Driver -# url: jdbc:mysql://localhost:3306/ry-vue?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8&autoReconnect=true&rewriteBatchedStatements=true&allowPublicKeyRetrieval=true&nullCatalogMeansCurrent=true -# username: -# password: -# oracle: -# type: ${spring.datasource.type} -# driverClassName: oracle.jdbc.OracleDriver -# url: jdbc:oracle:thin:@//localhost:1521/XE -# username: ROOT -# password: root -# postgres: -# type: ${spring.datasource.type} -# driverClassName: org.postgresql.Driver -# url: jdbc:postgresql://localhost:5432/postgres?useUnicode=true&characterEncoding=utf8&useSSL=true&autoReconnect=true&reWriteBatchedInserts=true -# username: root -# password: root -# sqlserver: -# type: ${spring.datasource.type} -# driverClassName: com.microsoft.sqlserver.jdbc.SQLServerDriver -# url: jdbc:sqlserver://localhost:1433;DatabaseName=tempdb;SelectMethod=cursor;encrypt=false;rewriteBatchedStatements=true -# username: SA -# password: root + # 推管库(行政检查信息同步目标库) + tgk: + lazy: true + url: jdbc:mysql://172.16.20.72:3306/zfjd_tgk?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8 + username: root + password: zdxt@8888 hikari: # 最大连接池数量 maxPoolSize: 500 diff --git a/zdxt-web-server/zdxt-admin-web-server/src/main/resources/application-prod.yml b/zdxt-web-server/zdxt-admin-web-server/src/main/resources/application-prod.yml index 642bd9a2..866fcd05 100644 --- a/zdxt-web-server/zdxt-admin-web-server/src/main/resources/application-prod.yml +++ b/zdxt-web-server/zdxt-admin-web-server/src/main/resources/application-prod.yml @@ -55,7 +55,7 @@ spring: lazy: true type: ${spring.datasource.type} driverClassName: com.mysql.cj.jdbc.Driver - url: jdbc:mysql://nortdsql.cloud.sz.gov.cn:15114,nortdsql-backup.cloud.sz.gov.cn:15114/zfjd_tgk?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8 + url: jdbc:mysql:loadbalance://10.134.89.36:15144,10.134.89.37:15144,10.134.89.38:15144,10.134.89.39:15144/zfjd_tgk?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8 username: zfjd password: szsf@zfjd v1: From 8d4e54e0dd8ea100c47bf7329f98a52528155d43 Mon Sep 17 00:00:00 2001 From: vincent Date: Wed, 4 Nov 2026 14:37:18 +0800 Subject: [PATCH 8/8] =?UTF-8?q?=E4=BF=AE=E6=94=B9=E4=BA=86=E4=BC=81?= =?UTF-8?q?=E4=B8=9A=E6=89=A7=E6=B3=95=E6=83=85=E5=86=B5=E6=9F=A5=E8=AF=A2?= =?UTF-8?q?=E7=9A=84SQL?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../report/EnforcementRegistrationReportMapper.xml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/zdxt-modules/zdxt-enforcement-code/src/main/resources/mapper/enforcementcode/report/EnforcementRegistrationReportMapper.xml b/zdxt-modules/zdxt-enforcement-code/src/main/resources/mapper/enforcementcode/report/EnforcementRegistrationReportMapper.xml index fdc1ca79..c37743f3 100644 --- a/zdxt-modules/zdxt-enforcement-code/src/main/resources/mapper/enforcementcode/report/EnforcementRegistrationReportMapper.xml +++ b/zdxt-modules/zdxt-enforcement-code/src/main/resources/mapper/enforcementcode/report/EnforcementRegistrationReportMapper.xml @@ -193,8 +193,8 @@ AND r.bureau_dept_name LIKE CONCAT('%', #{bo.bureauDeptName}, '%') - AND (law_enforcer LIKE CONCAT('%', #{bo.lawEnforcer}, '%') - ORr. law_enforcer_two LIKE CONCAT('%', #{bo.lawEnforcer}, '%')) + AND (r.law_enforcer LIKE CONCAT('%', #{bo.lawEnforcer}, '%') + OR r.law_enforcer_two LIKE CONCAT('%', #{bo.lawEnforcer}, '%')) AND r.enterprise_name LIKE CONCAT('%', #{bo.enterpriseName}, '%')