1、数据库PG切换为达梦的修改版本。
This commit is contained in:
+56
-17
@@ -1,47 +1,86 @@
|
||||
package com.Modules.etl.handler;
|
||||
|
||||
|
||||
|
||||
import com.fasterxml.jackson.core.JsonProcessingException;
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import org.apache.ibatis.type.BaseTypeHandler;
|
||||
import org.apache.ibatis.type.JdbcType;
|
||||
import org.apache.ibatis.type.MappedJdbcTypes;
|
||||
import org.apache.ibatis.type.MappedTypes;
|
||||
import java.sql.*;
|
||||
|
||||
import java.sql.CallableStatement;
|
||||
import java.sql.PreparedStatement;
|
||||
import java.sql.ResultSet;
|
||||
import java.sql.SQLException;
|
||||
import java.util.Base64;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 字节数组类型处理器 - 达梦数据库兼容版本(JSON格式)
|
||||
*
|
||||
* 将 Java byte[][] 与数据库 VARCHAR 列进行互转。
|
||||
* 存储格式: JSON 数组,每个元素为 Base64 编码字符串,如 ["YWJj","ZGVm"]
|
||||
* 空数组: 存储为 "[]"
|
||||
* null值: 存储为 NULL
|
||||
*
|
||||
* 原 PostgreSQL 版本使用 createArrayOf("bytea", ...) 创建原生 bytea 数组,
|
||||
* 达梦数据库不兼容此 API,改为 VARCHAR + JSON + Base64 存储。
|
||||
*/
|
||||
@MappedTypes(byte[][].class)
|
||||
@MappedJdbcTypes(JdbcType.ARRAY)
|
||||
@MappedJdbcTypes(JdbcType.VARCHAR)
|
||||
public class ArrayByteTypeHandler extends BaseTypeHandler<byte[][]> {
|
||||
|
||||
private static final ObjectMapper MAPPER = new ObjectMapper();
|
||||
|
||||
@Override
|
||||
public void setNonNullParameter(PreparedStatement ps, int i, byte[][] parameter, JdbcType jdbcType) throws SQLException {
|
||||
Array array = ps.getConnection().createArrayOf("bytea", parameter);
|
||||
ps.setArray(i, array);
|
||||
try {
|
||||
String[] encoded = new String[parameter.length];
|
||||
for (int j = 0; j < parameter.length; j++) {
|
||||
encoded[j] = Base64.getEncoder().encodeToString(parameter[j]);
|
||||
}
|
||||
ps.setString(i, MAPPER.writeValueAsString(encoded));
|
||||
} catch (JsonProcessingException e) {
|
||||
throw new SQLException("Failed to serialize byte[][] to JSON", e);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public byte[][] getNullableResult(ResultSet rs, String columnName) throws SQLException {
|
||||
return getArray(rs.getArray(columnName));
|
||||
return parseArray(rs.getString(columnName));
|
||||
}
|
||||
|
||||
@Override
|
||||
public byte[][] getNullableResult(ResultSet rs, int columnIndex) throws SQLException {
|
||||
return getArray(rs.getArray(columnIndex));
|
||||
return parseArray(rs.getString(columnIndex));
|
||||
}
|
||||
|
||||
@Override
|
||||
public byte[][] getNullableResult(CallableStatement cs, int columnIndex) throws SQLException {
|
||||
return getArray(cs.getArray(columnIndex));
|
||||
return parseArray(cs.getString(columnIndex));
|
||||
}
|
||||
|
||||
private byte[][] getArray(Array array) throws SQLException {
|
||||
if (array != null) {
|
||||
Object[] objArray = (Object[]) array.getArray();
|
||||
byte[][] result = new byte[objArray.length][];
|
||||
for (int i = 0; i < objArray.length; i++) {
|
||||
result[i] = (byte[]) objArray[i];
|
||||
private byte[][] parseArray(String value) {
|
||||
if (value == null || value.isEmpty()) {
|
||||
return new byte[0][];
|
||||
}
|
||||
try {
|
||||
// JSON 格式: ["abc","def"]
|
||||
List<String> list = MAPPER.readValue(value, MAPPER.getTypeFactory().constructCollectionType(List.class, String.class));
|
||||
byte[][] result = new byte[list.size()][];
|
||||
for (int i = 0; i < list.size(); i++) {
|
||||
String s = list.get(i);
|
||||
result[i] = (s == null || s.isEmpty()) ? new byte[0] : Base64.getDecoder().decode(s);
|
||||
}
|
||||
return result;
|
||||
} catch (JsonProcessingException e) {
|
||||
// 兼容旧的逗号分隔格式
|
||||
String[] parts = value.split(",", -1);
|
||||
byte[][] result = new byte[parts.length][];
|
||||
for (int i = 0; i < parts.length; i++) {
|
||||
String part = parts[i].trim();
|
||||
result[i] = part.isEmpty() ? new byte[0] : Base64.getDecoder().decode(part);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+45
-15
@@ -1,43 +1,73 @@
|
||||
package com.Modules.etl.handler;
|
||||
|
||||
|
||||
import com.fasterxml.jackson.core.JsonProcessingException;
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import org.apache.ibatis.type.BaseTypeHandler;
|
||||
import org.apache.ibatis.type.JdbcType;
|
||||
import org.apache.ibatis.type.MappedJdbcTypes;
|
||||
import org.apache.ibatis.type.MappedTypes;
|
||||
import java.sql.*;
|
||||
import java.util.Arrays;
|
||||
|
||||
import java.sql.CallableStatement;
|
||||
import java.sql.PreparedStatement;
|
||||
import java.sql.ResultSet;
|
||||
import java.sql.SQLException;
|
||||
|
||||
/**
|
||||
* 整型数组类型处理器 - 达梦数据库兼容版本(JSON格式)
|
||||
*
|
||||
* 将 Java Integer[] 与数据库 VARCHAR 列进行互转。
|
||||
* 存储格式: JSON 数组,如 [1,2,3]
|
||||
* 空数组: 存储为 "[]"
|
||||
* null值: 存储为 NULL
|
||||
*
|
||||
* 原 PostgreSQL 版本使用 createArrayOf("integer", ...) 创建原生数组,
|
||||
* 达梦数据库不兼容此 API,改为 VARCHAR + JSON 存储。
|
||||
*/
|
||||
@MappedTypes(Integer[].class)
|
||||
@MappedJdbcTypes(JdbcType.ARRAY)
|
||||
@MappedJdbcTypes(JdbcType.VARCHAR)
|
||||
public class ArrayIntegerTypeHandler extends BaseTypeHandler<Integer[]> {
|
||||
|
||||
private static final ObjectMapper MAPPER = new ObjectMapper();
|
||||
|
||||
@Override
|
||||
public void setNonNullParameter(PreparedStatement ps, int i, Integer[] parameter, JdbcType jdbcType) throws SQLException {
|
||||
Array array = ps.getConnection().createArrayOf("integer", parameter);
|
||||
ps.setArray(i, array);
|
||||
try {
|
||||
ps.setString(i, MAPPER.writeValueAsString(parameter));
|
||||
} catch (JsonProcessingException e) {
|
||||
throw new SQLException("Failed to serialize Integer[] to JSON", e);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Integer[] getNullableResult(ResultSet rs, String columnName) throws SQLException {
|
||||
return getArray(rs.getArray(columnName));
|
||||
return parseArray(rs.getString(columnName));
|
||||
}
|
||||
|
||||
@Override
|
||||
public Integer[] getNullableResult(ResultSet rs, int columnIndex) throws SQLException {
|
||||
return getArray(rs.getArray(columnIndex));
|
||||
return parseArray(rs.getString(columnIndex));
|
||||
}
|
||||
|
||||
@Override
|
||||
public Integer[] getNullableResult(CallableStatement cs, int columnIndex) throws SQLException {
|
||||
return getArray(cs.getArray(columnIndex));
|
||||
return parseArray(cs.getString(columnIndex));
|
||||
}
|
||||
|
||||
private Integer[] getArray(Array array) throws SQLException {
|
||||
if (array != null) {
|
||||
Object[] objArray = (Object[]) array.getArray();
|
||||
return Arrays.copyOf(objArray, objArray.length, Integer[].class);
|
||||
private Integer[] parseArray(String value) {
|
||||
if (value == null || value.isEmpty()) {
|
||||
return new Integer[0];
|
||||
}
|
||||
try {
|
||||
return MAPPER.readValue(value, Integer[].class);
|
||||
} catch (JsonProcessingException e) {
|
||||
// 兼容旧的逗号分隔格式
|
||||
String[] parts = value.split(",", -1);
|
||||
Integer[] result = new Integer[parts.length];
|
||||
for (int i = 0; i < parts.length; i++) {
|
||||
String part = parts[i].trim();
|
||||
result[i] = part.isEmpty() ? null : Integer.parseInt(part);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+39
-15
@@ -1,43 +1,67 @@
|
||||
package com.Modules.etl.handler;
|
||||
|
||||
|
||||
import com.fasterxml.jackson.core.JsonProcessingException;
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import org.apache.ibatis.type.BaseTypeHandler;
|
||||
import org.apache.ibatis.type.JdbcType;
|
||||
import org.apache.ibatis.type.MappedJdbcTypes;
|
||||
import org.apache.ibatis.type.MappedTypes;
|
||||
import java.sql.*;
|
||||
import java.util.Arrays;
|
||||
|
||||
import java.sql.CallableStatement;
|
||||
import java.sql.PreparedStatement;
|
||||
import java.sql.ResultSet;
|
||||
import java.sql.SQLException;
|
||||
|
||||
/**
|
||||
* 字符串数组类型处理器 - 达梦数据库兼容版本(JSON格式)
|
||||
*
|
||||
* 将 Java String[] 与数据库 VARCHAR 列进行互转。
|
||||
* 存储格式: JSON 数组,如 ["value1","value2","value3"]
|
||||
* 空数组: 存储为 "[]"
|
||||
* null值: 存储为 NULL
|
||||
*
|
||||
* 原 PostgreSQL 版本使用 createArrayOf("text", ...) 创建原生数组,
|
||||
* 达梦数据库不兼容此 API,改为 VARCHAR + JSON 存储。
|
||||
*/
|
||||
@MappedTypes(String[].class)
|
||||
@MappedJdbcTypes(JdbcType.ARRAY)
|
||||
@MappedJdbcTypes(JdbcType.VARCHAR)
|
||||
public class ArrayStringTypeHandler extends BaseTypeHandler<String[]> {
|
||||
|
||||
private static final ObjectMapper MAPPER = new ObjectMapper();
|
||||
|
||||
@Override
|
||||
public void setNonNullParameter(PreparedStatement ps, int i, String[] parameter, JdbcType jdbcType) throws SQLException {
|
||||
Array array = ps.getConnection().createArrayOf("text", parameter);
|
||||
ps.setArray(i, array);
|
||||
try {
|
||||
ps.setString(i, MAPPER.writeValueAsString(parameter));
|
||||
} catch (JsonProcessingException e) {
|
||||
throw new SQLException("Failed to serialize String[] to JSON", e);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String[] getNullableResult(ResultSet rs, String columnName) throws SQLException {
|
||||
return getArray(rs.getArray(columnName));
|
||||
return parseArray(rs.getString(columnName));
|
||||
}
|
||||
|
||||
@Override
|
||||
public String[] getNullableResult(ResultSet rs, int columnIndex) throws SQLException {
|
||||
return getArray(rs.getArray(columnIndex));
|
||||
return parseArray(rs.getString(columnIndex));
|
||||
}
|
||||
|
||||
@Override
|
||||
public String[] getNullableResult(CallableStatement cs, int columnIndex) throws SQLException {
|
||||
return getArray(cs.getArray(columnIndex));
|
||||
return parseArray(cs.getString(columnIndex));
|
||||
}
|
||||
|
||||
private String[] getArray(Array array) throws SQLException {
|
||||
if (array != null) {
|
||||
Object[] objArray = (Object[]) array.getArray();
|
||||
return Arrays.copyOf(objArray, objArray.length, String[].class);
|
||||
private String[] parseArray(String value) {
|
||||
if (value == null || value.isEmpty()) {
|
||||
return new String[0];
|
||||
}
|
||||
try {
|
||||
return MAPPER.readValue(value, String[].class);
|
||||
} catch (JsonProcessingException e) {
|
||||
// 兼容旧的逗号分隔格式
|
||||
return value.split(",", -1);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+7
-7
@@ -1,6 +1,6 @@
|
||||
package com.common.entity;
|
||||
|
||||
import java.time.OffsetDateTime;
|
||||
import java.time.LocalDateTime;
|
||||
|
||||
/**
|
||||
* 联动设备表实体类(防火墙设备信息)
|
||||
@@ -17,9 +17,9 @@ public class DeviceInterlocking {
|
||||
private String tenantId;
|
||||
private Long createDept;
|
||||
private Long createBy;
|
||||
private OffsetDateTime createTime;
|
||||
private LocalDateTime createTime;
|
||||
private Long updateBy;
|
||||
private OffsetDateTime updateTime;
|
||||
private LocalDateTime updateTime;
|
||||
private String remark;
|
||||
private String authUsername; // 用户名
|
||||
private String authPassword; // 密码
|
||||
@@ -55,14 +55,14 @@ public class DeviceInterlocking {
|
||||
public Long getCreateBy() { return createBy; }
|
||||
public void setCreateBy(Long createBy) { this.createBy = createBy; }
|
||||
|
||||
public OffsetDateTime getCreateTime() { return createTime; }
|
||||
public void setCreateTime(OffsetDateTime createTime) { this.createTime = createTime; }
|
||||
public LocalDateTime getCreateTime() { return createTime; }
|
||||
public void setCreateTime(LocalDateTime createTime) { this.createTime = createTime; }
|
||||
|
||||
public Long getUpdateBy() { return updateBy; }
|
||||
public void setUpdateBy(Long updateBy) { this.updateBy = updateBy; }
|
||||
|
||||
public OffsetDateTime getUpdateTime() { return updateTime; }
|
||||
public void setUpdateTime(OffsetDateTime updateTime) { this.updateTime = updateTime; }
|
||||
public LocalDateTime getUpdateTime() { return updateTime; }
|
||||
public void setUpdateTime(LocalDateTime updateTime) { this.updateTime = updateTime; }
|
||||
|
||||
public String getRemark() { return remark; }
|
||||
public void setRemark(String remark) { this.remark = remark; }
|
||||
|
||||
+7
-8
@@ -4,9 +4,8 @@ import com.Modules.etl.handler.ArrayIntegerTypeHandler;
|
||||
import com.Modules.etl.handler.ArrayStringTypeHandler;
|
||||
import org.apache.ibatis.type.JdbcType;
|
||||
import org.apache.ibatis.type.TypeHandler;
|
||||
import org.apache.ibatis.type.ArrayTypeHandler;
|
||||
|
||||
import java.time.OffsetDateTime;
|
||||
import java.time.LocalDateTime;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
|
||||
@@ -25,8 +24,8 @@ public class DeviceInterlockingCmd {
|
||||
private String banType; // 封禁类型(1:白名单、0:黑名单)
|
||||
private String cmdStatus; // 指令状态(0:未执行、1:已完成、2:执行中)
|
||||
private Integer banDuration; // 封禁时长(秒,-1表示永久)
|
||||
private OffsetDateTime createTime;
|
||||
private OffsetDateTime updateTime;
|
||||
private LocalDateTime createTime;
|
||||
private LocalDateTime updateTime;
|
||||
private String tenantId;
|
||||
private Long createDept;
|
||||
private Long createBy;
|
||||
@@ -65,11 +64,11 @@ public class DeviceInterlockingCmd {
|
||||
public Integer getBanDuration() { return banDuration; }
|
||||
public void setBanDuration(Integer banDuration) { this.banDuration = banDuration; }
|
||||
|
||||
public OffsetDateTime getCreateTime() { return createTime; }
|
||||
public void setCreateTime(OffsetDateTime createTime) { this.createTime = createTime; }
|
||||
public LocalDateTime getCreateTime() { return createTime; }
|
||||
public void setCreateTime(LocalDateTime createTime) { this.createTime = createTime; }
|
||||
|
||||
public OffsetDateTime getUpdateTime() { return updateTime; }
|
||||
public void setUpdateTime(OffsetDateTime updateTime) { this.updateTime = updateTime; }
|
||||
public LocalDateTime getUpdateTime() { return updateTime; }
|
||||
public void setUpdateTime(LocalDateTime updateTime) { this.updateTime = updateTime; }
|
||||
|
||||
public String getTenantId() { return tenantId; }
|
||||
public void setTenantId(String tenantId) { this.tenantId = tenantId; }
|
||||
|
||||
+10
-10
@@ -1,6 +1,6 @@
|
||||
package com.common.entity;
|
||||
|
||||
import java.time.OffsetDateTime;
|
||||
import java.time.LocalDateTime;
|
||||
|
||||
/**
|
||||
* 封禁记录表实体类
|
||||
@@ -12,15 +12,15 @@ public class DeviceInterlockingLog {
|
||||
private Long deviceInterlockingId; // 封禁设备ID
|
||||
private String banIp; // 封禁IP地址
|
||||
private String deviceName; // 封禁设备名称
|
||||
private OffsetDateTime banTime; // 封禁时间
|
||||
private LocalDateTime banTime; // 封禁时间
|
||||
private String banMethod; // 封禁方式(0.人工、1.自动化封禁)
|
||||
private Integer banResult; // 联动结果(成功:1、失败:0)
|
||||
private String tenantId;
|
||||
private Long createDept;
|
||||
private Long createBy;
|
||||
private OffsetDateTime createTime;
|
||||
private LocalDateTime createTime;
|
||||
private Long updateBy;
|
||||
private OffsetDateTime updateTime;
|
||||
private LocalDateTime updateTime;
|
||||
private String remark;
|
||||
private String respBody; // 响应body
|
||||
private String reqBody; // 请求body
|
||||
@@ -41,8 +41,8 @@ public class DeviceInterlockingLog {
|
||||
public String getDeviceName() { return deviceName; }
|
||||
public void setDeviceName(String deviceName) { this.deviceName = deviceName; }
|
||||
|
||||
public OffsetDateTime getBanTime() { return banTime; }
|
||||
public void setBanTime(OffsetDateTime banTime) { this.banTime = banTime; }
|
||||
public LocalDateTime getBanTime() { return banTime; }
|
||||
public void setBanTime(LocalDateTime banTime) { this.banTime = banTime; }
|
||||
|
||||
public String getBanMethod() { return banMethod; }
|
||||
public void setBanMethod(String banMethod) { this.banMethod = banMethod; }
|
||||
@@ -59,14 +59,14 @@ public class DeviceInterlockingLog {
|
||||
public Long getCreateBy() { return createBy; }
|
||||
public void setCreateBy(Long createBy) { this.createBy = createBy; }
|
||||
|
||||
public OffsetDateTime getCreateTime() { return createTime; }
|
||||
public void setCreateTime(OffsetDateTime createTime) { this.createTime = createTime; }
|
||||
public LocalDateTime getCreateTime() { return createTime; }
|
||||
public void setCreateTime(LocalDateTime createTime) { this.createTime = createTime; }
|
||||
|
||||
public Long getUpdateBy() { return updateBy; }
|
||||
public void setUpdateBy(Long updateBy) { this.updateBy = updateBy; }
|
||||
|
||||
public OffsetDateTime getUpdateTime() { return updateTime; }
|
||||
public void setUpdateTime(OffsetDateTime updateTime) { this.updateTime = updateTime; }
|
||||
public LocalDateTime getUpdateTime() { return updateTime; }
|
||||
public void setUpdateTime(LocalDateTime updateTime) { this.updateTime = updateTime; }
|
||||
|
||||
public String getRemark() { return remark; }
|
||||
public void setRemark(String remark) { this.remark = remark; }
|
||||
|
||||
+2
-2
@@ -15,7 +15,7 @@ public interface AlarmMapper {
|
||||
"INSERT INTO alarm (",
|
||||
"id, created_at, alarm_name, alarm_level, alarm_type, ",
|
||||
"alarm_major_type, alarm_minor_type,alarm_area_id, attack_ip, victim_ip, victim_web_url, ",
|
||||
"device_id, comment,origin_log_ids,log_start_at, log_end_at, window_time, http_status, ",
|
||||
"device_id, \"comment\",origin_log_ids,log_start_at, log_end_at, window_time, http_status, ",
|
||||
"attack_port, victim_port, attack_method, etl_time, log_count, ",
|
||||
"attack_chain_phase, disposition_advice, attack_direction, ",
|
||||
"judged_state, disposed_state, attack_result, fall, payload, dns_info, engine_type, " ,
|
||||
@@ -52,7 +52,7 @@ public interface AlarmMapper {
|
||||
@Insert("INSERT INTO alarm (" +
|
||||
"id, created_at, alarm_name, alarm_level, alarm_type, " +
|
||||
"alarm_major_type, alarm_minor_type,alarm_area_id, attack_ip, victim_ip, victim_web_url, " +
|
||||
"device_id, comment,origin_log_ids, log_start_at, log_end_at, window_time, http_status, " +
|
||||
"device_id, \"comment\",origin_log_ids, log_start_at, log_end_at, window_time, http_status, " +
|
||||
"attack_port, victim_port, attack_method, etl_time, log_count, " +
|
||||
"attack_chain_phase, disposition_advice, attack_direction, " +
|
||||
"judged_state, disposed_state, attack_result, fall, payload, dns_info, engine_type, " +
|
||||
|
||||
+2
-2
@@ -19,7 +19,7 @@ public interface AlarmVisitMapper {
|
||||
"INSERT INTO alarm_visit (",
|
||||
"id, created_at, alarm_name, alarm_level, alarm_type, ",
|
||||
"alarm_major_type, alarm_minor_type,alarm_area_id, attack_ip, victim_ip, victim_web_url, ",
|
||||
"device_id, comment,origin_log_ids,log_start_at, log_end_at,window_time, http_status, ",
|
||||
"device_id, \"comment\",origin_log_ids,log_start_at, log_end_at,window_time, http_status, ",
|
||||
"attack_port, victim_port, attack_method, etl_time, log_count, ",
|
||||
"attack_chain_phase, disposition_advice, attack_direction, ",
|
||||
"judged_state, disposed_state, attack_result, fall, payload, dns_info, engine_type, " ,
|
||||
@@ -56,7 +56,7 @@ public interface AlarmVisitMapper {
|
||||
@Insert("INSERT INTO alarm_visit (" +
|
||||
"id, created_at, alarm_name, alarm_level, alarm_type, " +
|
||||
"alarm_major_type, alarm_minor_type,alarm_area_id, attack_ip, victim_ip, victim_web_url, " +
|
||||
"device_id, comment,origin_log_ids, log_start_at, log_end_at, window_time,http_status, " +
|
||||
"device_id, \"comment\",origin_log_ids, log_start_at, log_end_at, window_time,http_status, " +
|
||||
"attack_port, victim_port, attack_method, etl_time, log_count, " +
|
||||
"attack_chain_phase, disposition_advice, attack_direction, " +
|
||||
"judged_state, disposed_state, attack_result, fall, payload, dns_info,engine_type, " +
|
||||
|
||||
+28
-13
@@ -37,22 +37,37 @@ public interface DeviceCollectHeartbeatMapper {
|
||||
|
||||
/**
|
||||
* 插入或更新(根据collect_id)
|
||||
* 达梦数据库使用 MERGE INTO 实现 upsert
|
||||
*/
|
||||
@Insert("INSERT INTO device_collect_heartbeat (" +
|
||||
@Update("MERGE INTO device_collect_heartbeat t " +
|
||||
"USING (SELECT " +
|
||||
"#{collectId} AS collect_id, " +
|
||||
"#{collectName} AS collect_name, " +
|
||||
"#{deviceIp} AS device_ip, " +
|
||||
"#{appVersion} AS app_version, " +
|
||||
"#{lastHeartbeat} AS last_heartbeat, " +
|
||||
"#{heartbeatCount} AS heartbeat_count, " +
|
||||
"#{status} AS status, " +
|
||||
"#{failCount} AS fail_count, " +
|
||||
"#{updateTime} AS update_time " +
|
||||
"FROM DUAL) s " +
|
||||
"ON (t.collect_id = s.collect_id) " +
|
||||
"WHEN MATCHED THEN UPDATE SET " +
|
||||
"t.collect_name = s.collect_name, " +
|
||||
"t.device_ip = s.device_ip, " +
|
||||
"t.app_version = s.app_version, " +
|
||||
"t.last_heartbeat = s.last_heartbeat, " +
|
||||
"t.heartbeat_count = s.heartbeat_count, " +
|
||||
"t.status = s.status, " +
|
||||
"t.fail_count = s.fail_count, " +
|
||||
"t.update_time = s.update_time " +
|
||||
"WHEN NOT MATCHED THEN INSERT (" +
|
||||
"collect_id, collect_name, device_ip, app_version, last_heartbeat, " +
|
||||
"heartbeat_count, status, fail_count, update_time " +
|
||||
"heartbeat_count, status, fail_count, update_time" +
|
||||
") VALUES (" +
|
||||
"#{collectId}, #{collectName}, #{deviceIp}, #{appVersion}, #{lastHeartbeat}, " +
|
||||
"#{heartbeatCount}, #{status}, #{failCount}, #{updateTime} " +
|
||||
") ON CONFLICT (collect_id) DO UPDATE SET " +
|
||||
"collect_name = EXCLUDED.collect_name, " +
|
||||
"device_ip = EXCLUDED.device_ip, " +
|
||||
"app_version = EXCLUDED.app_version, " +
|
||||
"last_heartbeat = EXCLUDED.last_heartbeat, " +
|
||||
"heartbeat_count = EXCLUDED.heartbeat_count, " +
|
||||
"status = EXCLUDED.status, " +
|
||||
"fail_count = EXCLUDED.fail_count, " +
|
||||
"update_time = EXCLUDED.update_time")
|
||||
"s.collect_id, s.collect_name, s.device_ip, s.app_version, s.last_heartbeat, " +
|
||||
"s.heartbeat_count, s.status, s.fail_count, s.update_time" +
|
||||
")")
|
||||
int upsert(DeviceCollectHeartbeat heartbeat);
|
||||
|
||||
/**
|
||||
|
||||
+8
-8
@@ -155,12 +155,12 @@ public interface DeviceCollectTaskMapper extends BaseMapper<DeviceCollectTask>{
|
||||
"<foreach collection='tasks' item='task' separator=';'>" +
|
||||
"UPDATE device_collect_task SET " +
|
||||
" first_time = CASE " +
|
||||
" WHEN first_time IS NULL AND #{task.firstTime}::TIMESTAMP IS NOT NULL THEN #{task.firstTime}::TIMESTAMP " +
|
||||
" WHEN first_time IS NULL AND #{task.firstTime} IS NOT NULL THEN #{task.firstTime} " +
|
||||
" ELSE first_time " +
|
||||
" END, " +
|
||||
" last_success_time = #{task.lastSuccessTime}::TIMESTAMP, " +
|
||||
" last_failed_time = #{task.lastFailedTime}::TIMESTAMP, " +
|
||||
" updated_at = #{task.updatedAt}::TIMESTAMP " +
|
||||
" last_success_time = #{task.lastSuccessTime}, " +
|
||||
" last_failed_time = #{task.lastFailedTime}, " +
|
||||
" updated_at = #{task.updatedAt} " +
|
||||
"WHERE id = #{task.id}" +
|
||||
"</foreach>" +
|
||||
"</script>")
|
||||
@@ -171,12 +171,12 @@ public interface DeviceCollectTaskMapper extends BaseMapper<DeviceCollectTask>{
|
||||
*/
|
||||
@Update("UPDATE device_collect_task " +
|
||||
"SET first_time = CASE " +
|
||||
" WHEN first_time IS NULL AND #{firstTime}::TIMESTAMP IS NOT NULL THEN #{firstTime}::TIMESTAMP " +
|
||||
" WHEN first_time IS NULL AND #{firstTime} IS NOT NULL THEN #{firstTime} " +
|
||||
" ELSE first_time " +
|
||||
" END, " +
|
||||
" last_success_time = #{lastSuccessTime}::TIMESTAMP, " +
|
||||
" last_failed_time = #{lastFailTime}::TIMESTAMP, " +
|
||||
" updated_at = #{updateTime}::TIMESTAMP " +
|
||||
" last_success_time = #{lastSuccessTime}, " +
|
||||
" last_failed_time = #{lastFailTime}, " +
|
||||
" updated_at = #{updateTime} " +
|
||||
"WHERE id = #{deviceCollectId}")
|
||||
int updateTaskTime(@Param("deviceCollectId") String deviceCollectId,
|
||||
@Param("firstTime") LocalDateTime firstTime,
|
||||
|
||||
+9
-6
@@ -61,8 +61,11 @@ public interface DeviceInterlockingCmdMapper {
|
||||
@Insert("INSERT INTO device_interlocking_cmd (probe_id, probe_ip, device_interlocking_id, device_interlocking_ip, " +
|
||||
"ban_ips, ban_method, ban_type, cmd_status, ban_duration, create_time, update_time, " +
|
||||
"tenant_id, create_dept, create_by, remark, ban_operation_type) " +
|
||||
"VALUES (#{probeId}, #{probeIp}, ARRAY[:ids], ARRAY[:ips], ARRAY[:banIps], " +
|
||||
"#{banMethod}, #{banType}, #{cmdStatus}, #{banDuration}, NOW(), NOW(), " +
|
||||
"VALUES (#{probeId}, #{probeIp}, " +
|
||||
"#{deviceInterlockingId, typeHandler=com.Modules.etl.handler.ArrayIntegerTypeHandler}, " +
|
||||
"#{deviceInterlockingIp, typeHandler=com.Modules.etl.handler.ArrayStringTypeHandler}, " +
|
||||
"#{banIps, typeHandler=com.Modules.etl.handler.ArrayStringTypeHandler}, " +
|
||||
"#{banMethod}, #{banType}, #{cmdStatus}, #{banDuration}, SYSDATE, SYSDATE, " +
|
||||
"#{tenantId}, #{createDept}, #{createBy}, #{remark}, #{banOperationType})")
|
||||
@Options(useGeneratedKeys = true, keyProperty = "id")
|
||||
int insert(DeviceInterlockingCmd cmd);
|
||||
@@ -73,25 +76,25 @@ public interface DeviceInterlockingCmdMapper {
|
||||
* @param cmdStatus 新状态
|
||||
* @return 影响行数
|
||||
*/
|
||||
@Update("UPDATE device_interlocking_cmd SET cmd_status = #{cmdStatus}, update_time = NOW() WHERE id = #{id}")
|
||||
@Update("UPDATE device_interlocking_cmd SET cmd_status = #{cmdStatus}, update_time = SYSDATE WHERE id = #{id}")
|
||||
int updateStatus(@Param("id") Long id, @Param("cmdStatus") String cmdStatus);
|
||||
|
||||
/**
|
||||
* 更新指令状态为执行中
|
||||
*/
|
||||
@Update("UPDATE device_interlocking_cmd SET cmd_status = '2', update_time = NOW() WHERE id = #{id}")
|
||||
@Update("UPDATE device_interlocking_cmd SET cmd_status = '2', update_time = SYSDATE WHERE id = #{id}")
|
||||
int updateStatusToExecuting(@Param("id") Long id);
|
||||
|
||||
/**
|
||||
* 更新指令状态为执行完成
|
||||
*/
|
||||
@Update("UPDATE device_interlocking_cmd SET cmd_status = '1', update_time = NOW() WHERE id = #{id}")
|
||||
@Update("UPDATE device_interlocking_cmd SET cmd_status = '1', update_time = SYSDATE WHERE id = #{id}")
|
||||
int updateStatusToCompleted(@Param("id") Long id);
|
||||
|
||||
/**
|
||||
* 更新指令状态为执行失败
|
||||
*/
|
||||
@Update("UPDATE device_interlocking_cmd SET cmd_status = '3', update_time = NOW() WHERE id = #{id}")
|
||||
@Update("UPDATE device_interlocking_cmd SET cmd_status = '3', update_time = SYSDATE WHERE id = #{id}")
|
||||
int updateStatusToFailed(@Param("id") Long id);
|
||||
|
||||
/**
|
||||
|
||||
+4
-4
@@ -84,7 +84,7 @@ public interface DeviceReceiveLogMapper {
|
||||
*/
|
||||
@Select("SELECT device_collect_id, MAX(created_at) AS last_success_time " +
|
||||
"FROM device_receive_log " +
|
||||
"WHERE push_success = true " +
|
||||
"WHERE push_success = 1 " +
|
||||
"AND created_at >= CURRENT_DATE " +
|
||||
"GROUP BY device_collect_id")
|
||||
List<DeviceCollectTaskTime> selectDailySuccessTimes();
|
||||
@@ -94,7 +94,7 @@ public interface DeviceReceiveLogMapper {
|
||||
*/
|
||||
@Select("SELECT device_collect_id, MAX(created_at) AS last_fail_time " +
|
||||
"FROM device_receive_log " +
|
||||
"WHERE push_success = false " +
|
||||
"WHERE push_success = 0 " +
|
||||
"AND created_at >= CURRENT_DATE " +
|
||||
"GROUP BY device_collect_id")
|
||||
List<DeviceCollectTaskTime> selectDailyFailTimes();
|
||||
@@ -104,7 +104,7 @@ public interface DeviceReceiveLogMapper {
|
||||
*/
|
||||
@Select("SELECT device_collect_id, MIN(created_at) AS first_success_time " +
|
||||
"FROM device_receive_log " +
|
||||
"WHERE push_success = true " +
|
||||
"WHERE push_success = 1 " +
|
||||
"GROUP BY device_collect_id")
|
||||
List<DeviceCollectTaskTime> selectFirstSuccessTimes();
|
||||
|
||||
@@ -114,7 +114,7 @@ public interface DeviceReceiveLogMapper {
|
||||
@Select("SELECT device_collect_id, MIN(created_at) AS first_time, " +
|
||||
"MAX(created_at) AS last_success_time " +
|
||||
"FROM device_receive_log " +
|
||||
"WHERE push_success = true " +
|
||||
"WHERE push_success = 1 " +
|
||||
"AND created_at >= #{startTime} " +
|
||||
"AND created_at < #{endTime} " +
|
||||
"GROUP BY device_collect_id")
|
||||
|
||||
+14
-15
@@ -49,30 +49,29 @@ public interface SyslogNormalAlarmMapper {
|
||||
*/
|
||||
@Select("SELECT " +
|
||||
"to_char(log_time, 'YYYYMMDD') as log_date, " +
|
||||
"ARRAY_AGG(DISTINCT host(src_ip)::text) as attack_ips, " +
|
||||
"WM_CONCAT(DISTINCT src_ip) as attack_ips, " +
|
||||
"origin_event_name, " +
|
||||
"MAX(attack_result) as attack_result, " +
|
||||
"MIN(log_time) as min_log_time, " +
|
||||
"MAX(log_time) as max_log_time, " +
|
||||
"COUNT(1) as log_count, " +
|
||||
"ARRAY_AGG(DISTINCT host(dest_ip)::text) as victim_ips, " +
|
||||
"ARRAY_AGG(DISTINCT http_url) as victim_web_urls, " +
|
||||
"ARRAY_AGG(DISTINCT device_id) as device_ids, " +
|
||||
"ARRAY_AGG(DISTINCT id) as origin_log_ids, " +
|
||||
"WM_CONCAT(DISTINCT dest_ip) as victim_ips, " +
|
||||
"WM_CONCAT(DISTINCT http_url) as victim_web_urls, " +
|
||||
"WM_CONCAT(DISTINCT device_id) as device_ids, " +
|
||||
"WM_CONCAT(DISTINCT id) as origin_log_ids, " +
|
||||
"MAX(event_level) as max_event_level, " +
|
||||
"MIN(origin_event_type) AS first_event_type, " +
|
||||
"MAX(origin_event_type) as event_type, " +
|
||||
"MIN(event_type) as min_event_type, " +
|
||||
"ARRAY_AGG(DISTINCT src_port::int4) as attack_ports, " +
|
||||
"ARRAY_AGG(DISTINCT dest_port::int4) as victim_ports, " +
|
||||
"ARRAY_AGG(DISTINCT http_resp_codes::text) as http_status_codes, " +
|
||||
"ARRAY_AGG(DISTINCT payload::BYTEA) as payload_samples, " +
|
||||
"ARRAY_AGG(DISTINCT http_req_header) as httpReqHeaders, " +
|
||||
"ARRAY_AGG(DISTINCT http_req_body) as httpReqBodys, " +
|
||||
"ARRAY_AGG(DISTINCT http_resp_header) as httpRespHeaders, " +
|
||||
"ARRAY_AGG(DISTINCT http_resp_body) as httpRespBodys, " +
|
||||
"MODE() WITHIN GROUP (ORDER BY dest_domain) as dns_info, " +
|
||||
"STRING_AGG(DISTINCT COALESCE(host(dest_ip)::text, ''), ',') as victim_ips_str " +
|
||||
"WM_CONCAT(DISTINCT src_port) as attack_ports, " +
|
||||
"WM_CONCAT(DISTINCT dest_port) as victim_ports, " +
|
||||
"WM_CONCAT(DISTINCT http_resp_codes) as http_status_codes, " +
|
||||
"WM_CONCAT(DISTINCT payload) as payload_samples, " +
|
||||
"WM_CONCAT(DISTINCT http_req_header) as httpReqHeaders, " +
|
||||
"WM_CONCAT(DISTINCT http_req_body) as httpReqBodys, " +
|
||||
"WM_CONCAT(DISTINCT http_resp_header) as httpRespHeaders, " +
|
||||
"WM_CONCAT(DISTINCT http_resp_body) as httpRespBodys, " +
|
||||
"LISTAGG(DISTINCT COALESCE(dest_ip, ''), ',') as victim_ips_str " +
|
||||
"FROM syslog_normal_alarm " +
|
||||
"WHERE log_time >= #{startTime} AND log_time < #{endTime} " +
|
||||
"AND event_level >= 1 AND src_ip NOT IN ('127.0.0.1', '127.0.0.2') " +
|
||||
|
||||
+14
-15
@@ -46,30 +46,29 @@ public interface SyslogNormalDataMapper {
|
||||
*/
|
||||
@Select("SELECT " +
|
||||
"to_char(log_time, 'YYYYMMDD') as log_date, " +
|
||||
"ARRAY_AGG(DISTINCT host(src_ip)::text) as attack_ips, " +
|
||||
"WM_CONCAT(DISTINCT src_ip) as attack_ips, " +
|
||||
"origin_event_name, " +
|
||||
"MAX(attack_result) as attack_result, " +
|
||||
"MIN(log_time) as min_log_time, " +
|
||||
"MAX(log_time) as max_log_time, " +
|
||||
"COUNT(1) as log_count, " +
|
||||
"ARRAY_AGG(DISTINCT host(dest_ip)::text) as victim_ips, " +
|
||||
"ARRAY_AGG(DISTINCT http_url) as victim_web_urls, " +
|
||||
"ARRAY_AGG(DISTINCT device_id) as device_ids, " +
|
||||
"ARRAY_AGG(DISTINCT id) as origin_log_ids, " +
|
||||
"WM_CONCAT(DISTINCT dest_ip) as victim_ips, " +
|
||||
"WM_CONCAT(DISTINCT http_url) as victim_web_urls, " +
|
||||
"WM_CONCAT(DISTINCT device_id) as device_ids, " +
|
||||
"WM_CONCAT(DISTINCT id) as origin_log_ids, " +
|
||||
"MAX(event_level) as max_event_level, " +
|
||||
"MIN(origin_event_type) AS first_event_type, " +
|
||||
"MAX(origin_event_type) as event_type, " +
|
||||
"MIN(event_type) as min_event_type, " +
|
||||
"ARRAY_AGG(DISTINCT src_port::int4) as attack_ports, " +
|
||||
"ARRAY_AGG(DISTINCT dest_port::int4) as victim_ports, " +
|
||||
"ARRAY_AGG(DISTINCT http_resp_codes::text) as http_status_codes, " +
|
||||
"ARRAY_AGG(DISTINCT payload::BYTEA) as payload_samples, " +
|
||||
"ARRAY_AGG(DISTINCT http_req_header) as httpReqHeaders, " +
|
||||
"ARRAY_AGG(DISTINCT http_req_body) as httpReqBodys, " +
|
||||
"ARRAY_AGG(DISTINCT http_resp_header) as httpRespHeaders, " +
|
||||
"ARRAY_AGG(DISTINCT http_resp_body) as httpRespBodys, " +
|
||||
"MODE() WITHIN GROUP (ORDER BY dest_domain) as dns_info, " +
|
||||
"STRING_AGG(DISTINCT COALESCE(host(dest_ip)::text, ''), ',') as victim_ips_str " +
|
||||
"WM_CONCAT(DISTINCT src_port) as attack_ports, " +
|
||||
"WM_CONCAT(DISTINCT dest_port) as victim_ports, " +
|
||||
"WM_CONCAT(DISTINCT http_resp_codes) as http_status_codes, " +
|
||||
"WM_CONCAT(DISTINCT payload) as payload_samples, " +
|
||||
"WM_CONCAT(DISTINCT http_req_header) as httpReqHeaders, " +
|
||||
"WM_CONCAT(DISTINCT http_req_body) as httpReqBodys, " +
|
||||
"WM_CONCAT(DISTINCT http_resp_header) as httpRespHeaders, " +
|
||||
"WM_CONCAT(DISTINCT http_resp_body) as httpRespBodys, " +
|
||||
"LISTAGG(DISTINCT COALESCE(dest_ip, ''), ',') as victim_ips_str " +
|
||||
"FROM syslog_normal_data " +
|
||||
"WHERE log_time >= #{startTime} AND log_time < #{endTime} " +
|
||||
"AND http_resp_codes =200 and origin_event_type <> '' and origin_event_name='访问日志' AND src_ip NOT IN ('127.0.0.1', '127.0.0.2') " +
|
||||
|
||||
+3
-3
@@ -18,12 +18,12 @@ public interface WecomNotificationMapper {
|
||||
"wecom_notification_time, tenant_id, create_dept, create_by, create_time, " +
|
||||
"update_by, update_time, remark, wecom_notification_status" +
|
||||
") VALUES (" +
|
||||
"nextval('seq_wecom_notification'), #{userId}, #{wecomNotificationName}, #{wecomNotificationIp}, " +
|
||||
"seq_wecom_notification.NEXTVAL, #{userId}, #{wecomNotificationName}, #{wecomNotificationIp}, " +
|
||||
"#{wecomNotificationType}, #{wecomNotificationLevel}, #{wecomNotificationContent}, " +
|
||||
"#{wecomNotificationTime}, #{tenantId}, #{createDept}, #{createBy}, #{createTime}, " +
|
||||
"#{updateBy}, #{updateTime}, #{remark}, #{wecomNotificationStatus}" +
|
||||
")")
|
||||
@SelectKey(statement = "SELECT currval('seq_wecom_notification')", keyProperty = "wecomNotificationId", resultType = Long.class, before = false)
|
||||
@SelectKey(statement = "SELECT seq_wecom_notification.currval", keyProperty = "wecomNotificationId", resultType = Long.class, before = false)
|
||||
int insert(WecomNotification notification);
|
||||
|
||||
/**
|
||||
@@ -41,7 +41,7 @@ public interface WecomNotificationMapper {
|
||||
/**
|
||||
* 更新通知状态
|
||||
*/
|
||||
@Update("UPDATE wecom_notification SET wecom_notification_status = #{status}, update_time = NOW() " +
|
||||
@Update("UPDATE wecom_notification SET wecom_notification_status = #{status}, update_time = SYSDATE " +
|
||||
"WHERE wecom_notification_id = #{wecomNotificationId}")
|
||||
int updateStatus(@Param("wecomNotificationId") Long wecomNotificationId, @Param("status") String status);
|
||||
}
|
||||
|
||||
+3
-3
@@ -4,7 +4,7 @@ import com.common.entity.DeviceInterlockingLog;
|
||||
import com.common.mapper.DeviceInterlockingLogMapper;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Service;
|
||||
import java.time.OffsetDateTime;
|
||||
import java.time.LocalDateTime;
|
||||
import java.util.List;
|
||||
|
||||
@Service
|
||||
@@ -32,7 +32,7 @@ public class DeviceInterlockingLogService {
|
||||
*/
|
||||
public int insert(DeviceInterlockingLog log) {
|
||||
if (log.getBanTime() == null) {
|
||||
log.setBanTime(OffsetDateTime.now());
|
||||
log.setBanTime(LocalDateTime.now());
|
||||
}
|
||||
return logMapper.insert(log);
|
||||
}
|
||||
@@ -44,7 +44,7 @@ public class DeviceInterlockingLogService {
|
||||
if (logs != null && !logs.isEmpty()) {
|
||||
for (DeviceInterlockingLog log : logs) {
|
||||
if (log.getBanTime() == null) {
|
||||
log.setBanTime(OffsetDateTime.now());
|
||||
log.setBanTime(LocalDateTime.now());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+36
-2
@@ -77,7 +77,7 @@ public class DmNormalizeRuleService {
|
||||
|
||||
List<Map<String, Object>> ruleMap=dmNormalizeRuleMapper.selectByDeviceId(id);
|
||||
sqlSession.commit();
|
||||
return ruleMap;
|
||||
return convertClobToString(ruleMap);
|
||||
|
||||
} catch (Exception e) {
|
||||
logger.error("DmNormalizeRuleService MyBatisUtil getSqlSession 异常", e);
|
||||
@@ -95,7 +95,41 @@ public class DmNormalizeRuleService {
|
||||
{
|
||||
System.out.println("调用selectByDeviceIdAuto 方法,id:"+id);
|
||||
List<Map<String, Object>> ruleMap=dmNormalizeRuleMapper.selectByDeviceId(id);
|
||||
return ruleMap;
|
||||
return convertClobToString(ruleMap);
|
||||
}
|
||||
|
||||
/**
|
||||
* 将达梦 JDBC CLOB/NCLOB 对象转换为 String,避免缓存序列化报错
|
||||
* 达梦驱动返回的 TEXT/CLOB 列可能是 dm.jdbc.driver.DmdbNClob 等内部类型,
|
||||
* toString() 只返回对象引用(如 DmdbNClob@xxx),必须通过 Clob 接口获取实际文本
|
||||
*/
|
||||
private List<Map<String, Object>> convertClobToString(List<Map<String, Object>> list) {
|
||||
if (list == null) return null;
|
||||
for (Map<String, Object> map : list) {
|
||||
if (map == null) continue;
|
||||
for (Map.Entry<String, Object> entry : map.entrySet()) {
|
||||
Object value = entry.getValue();
|
||||
if (value != null && value.getClass().getName().startsWith("dm.jdbc.")) {
|
||||
try {
|
||||
if (value instanceof java.sql.Clob) {
|
||||
java.sql.Clob clob = (java.sql.Clob) value;
|
||||
long length = clob.length();
|
||||
if (length > 0) {
|
||||
entry.setValue(clob.getSubString(1, (int) length));
|
||||
} else {
|
||||
entry.setValue("");
|
||||
}
|
||||
} else {
|
||||
entry.setValue(value.toString());
|
||||
}
|
||||
} catch (Exception e) {
|
||||
logger.warn("CLOB/NCLOB 转换 String 失败: " + e.getMessage());
|
||||
entry.setValue(null);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return list;
|
||||
}
|
||||
|
||||
}
|
||||
+18
@@ -734,7 +734,25 @@ public class RealtimeAnalysisEngine implements AnalysisEngine {
|
||||
return result;
|
||||
}
|
||||
// PostgreSQL数组以字符串形式返回,如 "{ip1,ip2,ip3}"
|
||||
// 达梦 JSONB_AGG 返回 JSON 数组格式,如 "[41614, 8080]"
|
||||
String str = value.toString();
|
||||
if (str.startsWith("[") && str.endsWith("]")) {
|
||||
str = str.substring(1, str.length() - 1).trim();
|
||||
if (str.isEmpty()) {
|
||||
return new String[0];
|
||||
}
|
||||
// 拆分 JSON 数组元素(兼容带引号和纯数字)
|
||||
String[] parts = str.split(",");
|
||||
String[] result = new String[parts.length];
|
||||
for (int i = 0; i < parts.length; i++) {
|
||||
String part = parts[i].trim();
|
||||
if (part.startsWith("\"") && part.endsWith("\"")) {
|
||||
part = part.substring(1, part.length() - 1);
|
||||
}
|
||||
result[i] = part;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
if (str.startsWith("{") && str.endsWith("}")) {
|
||||
str = str.substring(1, str.length() - 1);
|
||||
return str.split(",");
|
||||
|
||||
+13
-18
@@ -747,19 +747,19 @@ public class SqlGeneratorServiceImpl implements SqlGeneratorService {
|
||||
return "AVG(" + columnName + ")";
|
||||
case "DUPLICATESANDSPLICE":
|
||||
if (StringUtils.isNotBlank(argsStr)) {
|
||||
return "STRING_AGG(DISTINCT " + columnName + ", '" + argsStr + "')";
|
||||
return "LISTAGG(DISTINCT " + columnName + ", '" + argsStr + "')";
|
||||
}
|
||||
return "STRING_AGG(DISTINCT " + columnName + ", ',')";
|
||||
return "LISTAGG(DISTINCT " + columnName + ", ',')";
|
||||
case "CONCAT_AGG":
|
||||
if (StringUtils.isNotBlank(argsStr)) {
|
||||
return "STRING_AGG(" + columnName + ", '" + argsStr + "')";
|
||||
return "LISTAGG(" + columnName + ", '" + argsStr + "')";
|
||||
}
|
||||
return "STRING_AGG(" + columnName + ", ',')";
|
||||
return "LISTAGG(" + columnName + ", ',')";
|
||||
case "CONCAT_AGG_ID":
|
||||
if (StringUtils.isNotBlank(argsStr)) {
|
||||
return "STRING_AGG(" + columnName + ", '" + argsStr + "')";
|
||||
return "LISTAGG(" + columnName + ", '" + argsStr + "')";
|
||||
}
|
||||
return "STRING_AGG(" + columnName + ", ',')";
|
||||
return "LISTAGG(" + columnName + ", ',')";
|
||||
case "SPLIT_DISTINCT_CONCAT":
|
||||
if (StringUtils.isNotBlank(argsStr)) {
|
||||
String[] splitArgs = argsStr.split(",");
|
||||
@@ -767,23 +767,23 @@ public class SqlGeneratorServiceImpl implements SqlGeneratorService {
|
||||
String separator = splitArgs[0].trim();
|
||||
String delimiter = splitArgs[1].trim();
|
||||
String limit = splitArgs[2].trim();
|
||||
return "STRING_AGG(DISTINCT REGEXP_SPLIT(" + columnName + ", '" + delimiter + "'), '" + separator + "') LIMIT " + limit;
|
||||
return "LISTAGG(DISTINCT REGEXP_SPLIT(" + columnName + ", '" + delimiter + "'), '" + separator + "') LIMIT " + limit;
|
||||
}
|
||||
}
|
||||
return columnName;
|
||||
//自定添加方法
|
||||
case "MODE_WITH_GROUP":
|
||||
return "MODE() WITHIN GROUP (ORDER BY " + columnName + ")";
|
||||
return columnName;
|
||||
|
||||
// 聚合函数(兼容旧代码)
|
||||
case "ARRAY_AGG":
|
||||
|
||||
return "ARRAY_AGG(DISTINCT " + columnName + ")";
|
||||
return "WM_CONCAT(DISTINCT " + columnName + ")";
|
||||
case "STRING_AGG":
|
||||
if (StringUtils.isNotBlank(argsStr)) {
|
||||
return "STRING_AGG(" + columnSafeWrap(columnName) + ", " + argsStr + ")";
|
||||
return "LISTAGG(" + columnSafeWrap(columnName) + ", " + argsStr + ")";
|
||||
}
|
||||
return "STRING_AGG(DISTINCT " + columnName + ", ',')";
|
||||
return "LISTAGG(DISTINCT " + columnName + ", ',')";
|
||||
|
||||
// 时间函数
|
||||
case "YEAR":
|
||||
@@ -847,7 +847,7 @@ public class SqlGeneratorServiceImpl implements SqlGeneratorService {
|
||||
case "TO_CHAR":
|
||||
return "TO_CHAR(" + columnName + ", 'YYYYMMDD')";
|
||||
case "HOST":
|
||||
return "HOST(" + columnName + ")::text";
|
||||
return columnName;
|
||||
default:
|
||||
return functionName + "(" + columnName + ")";
|
||||
}
|
||||
@@ -938,12 +938,7 @@ public class SqlGeneratorServiceImpl implements SqlGeneratorService {
|
||||
* 列名安全包装(处理类型转换)
|
||||
*/
|
||||
private String columnSafeWrap(String columnName) {
|
||||
if (columnName.toLowerCase().contains("ip")) {
|
||||
return "host(" + columnName + ")::text";
|
||||
}
|
||||
if (columnName.toLowerCase().contains("port")) {
|
||||
return columnName + "::int4";
|
||||
}
|
||||
// DM不需要类型转换,直接返回列名
|
||||
return columnName;
|
||||
}
|
||||
|
||||
|
||||
@@ -22,6 +22,18 @@ public class JsonbUtil {
|
||||
return null;
|
||||
}
|
||||
|
||||
// 达梦数据库:TEXT/CLOB 列返回 dm.jdbc.driver.DmdbNClob 对象,
|
||||
// toString() 只返回对象引用而非实际内容,必须通过 Clob 接口读取
|
||||
if (value instanceof java.sql.Clob) {
|
||||
try {
|
||||
java.sql.Clob clob = (java.sql.Clob) value;
|
||||
long length = clob.length();
|
||||
value = length > 0 ? clob.getSubString(1, (int) length) : "";
|
||||
} catch (Exception e) {
|
||||
value = value.toString();
|
||||
}
|
||||
}
|
||||
|
||||
// 如果已经是字符串,直接返回
|
||||
if (value instanceof String) {
|
||||
String strValue = (String) value;
|
||||
|
||||
@@ -1,8 +1,16 @@
|
||||
package com.config;
|
||||
|
||||
import com.fasterxml.jackson.core.JsonGenerator;
|
||||
import com.fasterxml.jackson.databind.BeanDescription;
|
||||
import com.fasterxml.jackson.databind.JsonSerializer;
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import com.fasterxml.jackson.databind.SerializationConfig;
|
||||
import com.fasterxml.jackson.databind.SerializerProvider;
|
||||
import com.fasterxml.jackson.databind.jsontype.BasicPolymorphicTypeValidator;
|
||||
import com.fasterxml.jackson.databind.jsontype.PolymorphicTypeValidator;
|
||||
import com.fasterxml.jackson.databind.jsontype.TypeSerializer;
|
||||
import com.fasterxml.jackson.databind.module.SimpleModule;
|
||||
import com.fasterxml.jackson.databind.ser.BeanSerializerModifier;
|
||||
import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule;
|
||||
import org.springframework.cache.CacheManager;
|
||||
import org.springframework.cache.annotation.EnableCaching;
|
||||
@@ -15,6 +23,7 @@ import org.springframework.data.redis.serializer.GenericJackson2JsonRedisSeriali
|
||||
import org.springframework.data.redis.serializer.RedisSerializationContext;
|
||||
import org.springframework.data.redis.serializer.StringRedisSerializer;
|
||||
import com.fasterxml.jackson.databind.DeserializationFeature;
|
||||
import java.io.IOException;
|
||||
import java.time.Duration;
|
||||
import java.util.Collections;
|
||||
import org.springframework.context.annotation.Primary;
|
||||
@@ -35,6 +44,33 @@ public class CacheConfig {
|
||||
// 禁用将日期序列化为时间戳
|
||||
mapper.disable(com.fasterxml.jackson.databind.SerializationFeature.WRITE_DATES_AS_TIMESTAMPS);
|
||||
|
||||
// 注册达梦 JDBC 安全序列化器 — 拦截 dm.jdbc.* 类,直接返回 null 防止循环引用 StackOverflow
|
||||
SimpleModule dmSafeModule = new SimpleModule("dm-safe");
|
||||
dmSafeModule.setSerializerModifier(new BeanSerializerModifier() {
|
||||
@Override
|
||||
public JsonSerializer<?> modifySerializer(SerializationConfig config,
|
||||
BeanDescription beanDesc,
|
||||
JsonSerializer<?> serializer) {
|
||||
if (beanDesc.getBeanClass().getName().startsWith("dm.jdbc.")) {
|
||||
return new JsonSerializer<Object>() {
|
||||
@Override
|
||||
public void serialize(Object value, JsonGenerator gen,
|
||||
SerializerProvider serializers) throws IOException {
|
||||
gen.writeNull();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void serializeWithType(Object value, JsonGenerator gen,
|
||||
SerializerProvider serializers, TypeSerializer typeSer) throws IOException {
|
||||
gen.writeNull();
|
||||
}
|
||||
};
|
||||
}
|
||||
return serializer;
|
||||
}
|
||||
});
|
||||
mapper.registerModule(dmSafeModule);
|
||||
|
||||
// 启用类型信息,解决 LinkedHashMap 转换问题
|
||||
PolymorphicTypeValidator ptv = BasicPolymorphicTypeValidator.builder()
|
||||
.allowIfSubType("com.common.entity.") // 允许你的实体类包
|
||||
|
||||
@@ -1,6 +1,14 @@
|
||||
package com.config;
|
||||
|
||||
import com.fasterxml.jackson.core.JsonGenerator;
|
||||
import com.fasterxml.jackson.databind.BeanDescription;
|
||||
import com.fasterxml.jackson.databind.JsonSerializer;
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import com.fasterxml.jackson.databind.SerializationConfig;
|
||||
import com.fasterxml.jackson.databind.SerializerProvider;
|
||||
import com.fasterxml.jackson.databind.jsontype.TypeSerializer;
|
||||
import com.fasterxml.jackson.databind.module.SimpleModule;
|
||||
import com.fasterxml.jackson.databind.ser.BeanSerializerModifier;
|
||||
import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
@@ -9,6 +17,8 @@ import org.springframework.data.redis.core.RedisTemplate;
|
||||
import org.springframework.data.redis.serializer.Jackson2JsonRedisSerializer;
|
||||
import org.springframework.data.redis.serializer.StringRedisSerializer;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
@Configuration
|
||||
public class RedisConfig {
|
||||
|
||||
@@ -23,6 +33,32 @@ public class RedisConfig {
|
||||
|
||||
ObjectMapper mapper = new ObjectMapper();
|
||||
mapper.registerModule(new JavaTimeModule());
|
||||
// 注册达梦 JDBC 安全序列化器 — 拦截 dm.jdbc.* 类,直接返回 null 防止循环引用 StackOverflow
|
||||
SimpleModule dmSafeModule = new SimpleModule("dm-safe");
|
||||
dmSafeModule.setSerializerModifier(new BeanSerializerModifier() {
|
||||
@Override
|
||||
public JsonSerializer<?> modifySerializer(SerializationConfig config,
|
||||
BeanDescription beanDesc,
|
||||
JsonSerializer<?> serializer) {
|
||||
if (beanDesc.getBeanClass().getName().startsWith("dm.jdbc.")) {
|
||||
return new JsonSerializer<Object>() {
|
||||
@Override
|
||||
public void serialize(Object value, JsonGenerator gen,
|
||||
SerializerProvider serializers) throws IOException {
|
||||
gen.writeNull();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void serializeWithType(Object value, JsonGenerator gen,
|
||||
SerializerProvider serializers, TypeSerializer typeSer) throws IOException {
|
||||
gen.writeNull();
|
||||
}
|
||||
};
|
||||
}
|
||||
return serializer;
|
||||
}
|
||||
});
|
||||
mapper.registerModule(dmSafeModule);
|
||||
mapper.activateDefaultTyping(
|
||||
mapper.getPolymorphicTypeValidator(),
|
||||
ObjectMapper.DefaultTyping.NON_FINAL
|
||||
|
||||
@@ -1,8 +1,16 @@
|
||||
package com.config;
|
||||
|
||||
|
||||
import com.fasterxml.jackson.core.JsonGenerator;
|
||||
import com.fasterxml.jackson.databind.BeanDescription;
|
||||
import com.fasterxml.jackson.databind.DeserializationFeature;
|
||||
import com.fasterxml.jackson.databind.JsonSerializer;
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import com.fasterxml.jackson.databind.SerializationConfig;
|
||||
import com.fasterxml.jackson.databind.SerializerProvider;
|
||||
import com.fasterxml.jackson.databind.jsontype.TypeSerializer;
|
||||
import com.fasterxml.jackson.databind.module.SimpleModule;
|
||||
import com.fasterxml.jackson.databind.ser.BeanSerializerModifier;
|
||||
import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
@@ -10,6 +18,7 @@ import org.springframework.http.converter.HttpMessageConverter;
|
||||
import org.springframework.http.converter.json.MappingJackson2HttpMessageConverter;
|
||||
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.List;
|
||||
|
||||
@Configuration
|
||||
@@ -28,6 +37,33 @@ public class WebConfig implements WebMvcConfigurer {
|
||||
// 禁用将日期序列化为时间戳
|
||||
mapper.disable(com.fasterxml.jackson.databind.SerializationFeature.WRITE_DATES_AS_TIMESTAMPS);
|
||||
|
||||
// 注册达梦 JDBC 安全序列化器 — 拦截 dm.jdbc.* 类,直接返回 null 防止循环引用 StackOverflow
|
||||
SimpleModule dmSafeModule = new SimpleModule("dm-safe");
|
||||
dmSafeModule.setSerializerModifier(new BeanSerializerModifier() {
|
||||
@Override
|
||||
public JsonSerializer<?> modifySerializer(SerializationConfig config,
|
||||
BeanDescription beanDesc,
|
||||
JsonSerializer<?> serializer) {
|
||||
if (beanDesc.getBeanClass().getName().startsWith("dm.jdbc.")) {
|
||||
return new JsonSerializer<Object>() {
|
||||
@Override
|
||||
public void serialize(Object value, JsonGenerator gen,
|
||||
SerializerProvider serializers) throws IOException {
|
||||
gen.writeNull();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void serializeWithType(Object value, JsonGenerator gen,
|
||||
SerializerProvider serializers, TypeSerializer typeSer) throws IOException {
|
||||
gen.writeNull();
|
||||
}
|
||||
};
|
||||
}
|
||||
return serializer;
|
||||
}
|
||||
});
|
||||
mapper.registerModule(dmSafeModule);
|
||||
|
||||
// 忽略未知属性
|
||||
mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user