chore: 项目环境升级为 JDK25,Spring 4.1,项目重构为多模块
This commit is contained in:
21
server/manuagent-common/pom.xml
Normal file
21
server/manuagent-common/pom.xml
Normal file
@@ -0,0 +1,21 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<parent>
|
||||
<groupId>tech.easyflow</groupId>
|
||||
<artifactId>manuagent-parent</artifactId>
|
||||
<version>0.1.0</version>
|
||||
</parent>
|
||||
<artifactId>manuagent-common</artifactId>
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>org.springframework</groupId>
|
||||
<artifactId>spring-web</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.mybatis</groupId>
|
||||
<artifactId>mybatis</artifactId>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
</project>
|
||||
@@ -0,0 +1,15 @@
|
||||
package tech.easyflow.manuagent.common;
|
||||
|
||||
import java.time.Instant;
|
||||
|
||||
/**
|
||||
* 统一接口错误响应。
|
||||
*
|
||||
* @param code 稳定错误码
|
||||
* @param message 可理解错误信息
|
||||
* @param traceId 日志关联标识
|
||||
* @param timestamp 发生时间
|
||||
*/
|
||||
public record ApiError(String code, String message, String traceId, Instant timestamp) {
|
||||
}
|
||||
|
||||
@@ -0,0 +1,44 @@
|
||||
package tech.easyflow.manuagent.common;
|
||||
|
||||
import org.springframework.http.HttpStatus;
|
||||
|
||||
/**
|
||||
* 可安全返回给调用方的业务异常。
|
||||
*/
|
||||
public class ApiException extends RuntimeException {
|
||||
|
||||
private final HttpStatus status;
|
||||
private final String code;
|
||||
|
||||
/**
|
||||
* 创建业务异常。
|
||||
*
|
||||
* @param status HTTP 状态
|
||||
* @param code 稳定错误码
|
||||
* @param message 可操作错误说明
|
||||
*/
|
||||
public ApiException(HttpStatus status, String code, String message) {
|
||||
super(message);
|
||||
this.status = status;
|
||||
this.code = code;
|
||||
}
|
||||
|
||||
/**
|
||||
* 返回 HTTP 状态。
|
||||
*
|
||||
* @return HTTP 状态
|
||||
*/
|
||||
public HttpStatus status() {
|
||||
return status;
|
||||
}
|
||||
|
||||
/**
|
||||
* 返回稳定错误码。
|
||||
*
|
||||
* @return 错误码
|
||||
*/
|
||||
public String code() {
|
||||
return code;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,56 @@
|
||||
package tech.easyflow.manuagent.common.typehandler;
|
||||
|
||||
import java.sql.CallableStatement;
|
||||
import java.sql.PreparedStatement;
|
||||
import java.sql.ResultSet;
|
||||
import java.sql.SQLException;
|
||||
import java.sql.Types;
|
||||
import org.apache.ibatis.type.BaseTypeHandler;
|
||||
import org.apache.ibatis.type.JdbcType;
|
||||
import org.apache.ibatis.type.MappedJdbcTypes;
|
||||
import org.apache.ibatis.type.MappedTypes;
|
||||
|
||||
/**
|
||||
* 将 JSON 文本映射到数据库的原生 JSON/JSONB 列。
|
||||
*
|
||||
* <p>当前 PostgreSQL 阶段使用 JDBC {@link Types#OTHER} 发送 JSON 文本,使驱动按目标列类型完成绑定,
|
||||
* 避免在业务 SQL 中重复书写字符串拼接或手工创建驱动专有对象。未来适配国产数据库时,只需替换
|
||||
* 该类型处理器或按数据库方言提供对应实现,实体和服务层无需感知。</p>
|
||||
*/
|
||||
@MappedTypes(String.class)
|
||||
@MappedJdbcTypes(JdbcType.OTHER)
|
||||
public class JsonbStringTypeHandler extends BaseTypeHandler<String> {
|
||||
|
||||
/**
|
||||
* 以数据库原生扩展类型绑定非空 JSON 文本。
|
||||
*
|
||||
* @param statement 预编译语句
|
||||
* @param index 参数位置
|
||||
* @param parameter JSON 文本
|
||||
* @param jdbcType MyBatis 推断的 JDBC 类型
|
||||
* @throws SQLException 参数绑定失败时抛出
|
||||
*/
|
||||
@Override
|
||||
public void setNonNullParameter(
|
||||
PreparedStatement statement, int index, String parameter, JdbcType jdbcType) throws SQLException {
|
||||
statement.setObject(index, parameter, Types.OTHER);
|
||||
}
|
||||
|
||||
/** 按列名读取 JSON 文本。 */
|
||||
@Override
|
||||
public String getNullableResult(ResultSet resultSet, String columnName) throws SQLException {
|
||||
return resultSet.getString(columnName);
|
||||
}
|
||||
|
||||
/** 按列序号读取 JSON 文本。 */
|
||||
@Override
|
||||
public String getNullableResult(ResultSet resultSet, int columnIndex) throws SQLException {
|
||||
return resultSet.getString(columnIndex);
|
||||
}
|
||||
|
||||
/** 从存储过程结果读取 JSON 文本。 */
|
||||
@Override
|
||||
public String getNullableResult(CallableStatement statement, int columnIndex) throws SQLException {
|
||||
return statement.getString(columnIndex);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,98 @@
|
||||
package tech.easyflow.manuagent.common.typehandler;
|
||||
|
||||
import java.sql.CallableStatement;
|
||||
import java.sql.PreparedStatement;
|
||||
import java.sql.ResultSet;
|
||||
import java.sql.SQLException;
|
||||
import java.util.UUID;
|
||||
import org.apache.ibatis.type.BaseTypeHandler;
|
||||
import org.apache.ibatis.type.JdbcType;
|
||||
import org.apache.ibatis.type.MappedJdbcTypes;
|
||||
import org.apache.ibatis.type.MappedTypes;
|
||||
|
||||
/**
|
||||
* 在 Java {@link UUID} 与数据库 UUID 值之间进行显式转换。
|
||||
*
|
||||
* <p>PostgreSQL 驱动读取 {@code uuid} 列时通常直接返回 {@link UUID},但不同驱动或查询表达式也可能
|
||||
* 返回字符串。该处理器同时兼容两种结果,并通过 {@link PreparedStatement#setObject(int, Object)}
|
||||
* 保留数据库驱动对原生 UUID 类型的绑定能力,避免把 UUID 降级成易产生隐式转换的 VARCHAR。</p>
|
||||
*/
|
||||
@MappedTypes(UUID.class)
|
||||
@MappedJdbcTypes(value = JdbcType.OTHER, includeNullJdbcType = true)
|
||||
public class UuidTypeHandler extends BaseTypeHandler<UUID> {
|
||||
|
||||
/**
|
||||
* 将非空 UUID 作为驱动原生对象写入预编译语句。
|
||||
*
|
||||
* @param statement 预编译语句
|
||||
* @param index 参数位置
|
||||
* @param parameter 待写入的 UUID
|
||||
* @param jdbcType MyBatis 推断的 JDBC 类型
|
||||
* @throws SQLException 数据库驱动拒绝绑定参数时抛出
|
||||
*/
|
||||
@Override
|
||||
public void setNonNullParameter(
|
||||
PreparedStatement statement, int index, UUID parameter, JdbcType jdbcType) throws SQLException {
|
||||
statement.setObject(index, parameter);
|
||||
}
|
||||
|
||||
/**
|
||||
* 按列名读取 UUID。
|
||||
*
|
||||
* @param resultSet 查询结果集
|
||||
* @param columnName 列名
|
||||
* @return UUID,数据库值为空时返回 {@code null}
|
||||
* @throws SQLException 读取或转换失败时抛出
|
||||
*/
|
||||
@Override
|
||||
public UUID getNullableResult(ResultSet resultSet, String columnName) throws SQLException {
|
||||
return toUuid(resultSet.getObject(columnName));
|
||||
}
|
||||
|
||||
/**
|
||||
* 按列序号读取 UUID。
|
||||
*
|
||||
* @param resultSet 查询结果集
|
||||
* @param columnIndex 列序号
|
||||
* @return UUID,数据库值为空时返回 {@code null}
|
||||
* @throws SQLException 读取或转换失败时抛出
|
||||
*/
|
||||
@Override
|
||||
public UUID getNullableResult(ResultSet resultSet, int columnIndex) throws SQLException {
|
||||
return toUuid(resultSet.getObject(columnIndex));
|
||||
}
|
||||
|
||||
/**
|
||||
* 从存储过程结果中读取 UUID。
|
||||
*
|
||||
* @param statement 存储过程调用语句
|
||||
* @param columnIndex 列序号
|
||||
* @return UUID,数据库值为空时返回 {@code null}
|
||||
* @throws SQLException 读取或转换失败时抛出
|
||||
*/
|
||||
@Override
|
||||
public UUID getNullableResult(CallableStatement statement, int columnIndex) throws SQLException {
|
||||
return toUuid(statement.getObject(columnIndex));
|
||||
}
|
||||
|
||||
/**
|
||||
* 统一处理驱动返回的 UUID 对象或字符串。
|
||||
*
|
||||
* @param value 驱动返回值
|
||||
* @return 规范化后的 UUID,空值返回 {@code null}
|
||||
* @throws SQLException 返回值不是合法 UUID 时抛出并保留数据库访问语义
|
||||
*/
|
||||
private UUID toUuid(Object value) throws SQLException {
|
||||
if (value == null) {
|
||||
return null;
|
||||
}
|
||||
if (value instanceof UUID uuid) {
|
||||
return uuid;
|
||||
}
|
||||
try {
|
||||
return UUID.fromString(value.toString());
|
||||
} catch (IllegalArgumentException exception) {
|
||||
throw new SQLException("数据库返回了无法转换为 UUID 的值: " + value, exception);
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user