APIJSON icon indicating copy to clipboard operation
APIJSON copied to clipboard

[咨询] 字段映射问题

Open hany5725 opened this issue 3 months ago • 8 comments

Description

我使用字段映射功能,重写了setColumn和getKey方法,在初始化时正常输入内容,但是当我调用查询时,ColumnUtil.VERSIONED_KEY_COLUMN_MAP为空了

代码内容 public class TunnelSqlConfig extends APIJSONSQLConfig<String> {

/**
 * 默认构造函数
 */
public TunnelSqlConfig() {
    super();
}

/**
 * 带参数构造函数
 *
 * @param method 请求方法
 * @param table  表名
 */
public TunnelSqlConfig(RequestMethod method, String table) {
    super(method, table);
}

static {
    // 设置逻辑删除字段
    KEY_DELETED_KEY = "del_flag";
    KEY_DELETED_VALUE = "1";
    KEY_NOT_DELETED_VALUE = "0";
    // 设置默认数据库类型和模式
    DEFAULT_DATABASE = DATABASE_MYSQL;
    DEFAULT_SCHEMA = SystemProperties.Database.getDefaultSchema();

    // 配置SQL配置回调
    SIMPLE_CALLBACK = new SimpleCallback<String>() {

        /**
         * 获取SQL配置实例
         *
         * @param method     请求方法
         * @param database   数据库名
         * @param schema     模式名
         * @param datasource 数据源名
         * @param table      表名
         * @return SQL配置实例
         */
        @Override
        public AbstractSQLConfig<String> getSQLConfig(RequestMethod method, String database, String schema, String datasource, String table) {
            return new TunnelSqlConfig(method, table);
        }

        /**
         * 获取用户ID字段名
         *
         * @param database   数据库名
         * @param schema     模式名
         * @param datasource 数据源名
         * @param table      表名
         * @return 用户ID字段名
         */
        @Override
        public String getUserIdKey(String database, String schema, String datasource, String table) {
            return USER_.equals(table) || PRIVACY_.equals(table) ? ID : USER_ID;
        }
    };

    Map<String, Map<String, String>> tableKeyColumnMap = new HashMap<>();
    Map<String, String> ballastlessLedgerColumnMap = new HashMap<>();
    ballastlessLedgerColumnMap.put("id", "id");
    ballastlessLedgerColumnMap.put("lineName", "line_name");
    ballastlessLedgerColumnMap.put("lineLevel", "line_level");
    ballastlessLedgerColumnMap.put("bureauName", "bureau_name");
    ballastlessLedgerColumnMap.put("divisionName", "division_name");
    ballastlessLedgerColumnMap.put("sectionName", "section_name");
    ballastlessLedgerColumnMap.put("direction", "direction");
    ballastlessLedgerColumnMap.put("locationType", "location_type");
    ballastlessLedgerColumnMap.put("locationName", "location_name");
    ballastlessLedgerColumnMap.put("sectionNumber", "section_number");
    ballastlessLedgerColumnMap.put("equipmentCode", "equipment_code");
    ballastlessLedgerColumnMap.put("startMileage", "start_mileage");
    ballastlessLedgerColumnMap.put("endMileage", "end_mileage");
    ballastlessLedgerColumnMap.put("centerMileage", "center_mileage");
    ballastlessLedgerColumnMap.put("overallLength", "overall_length");
    ballastlessLedgerColumnMap.put("trackType", "track_type");
    ballastlessLedgerColumnMap.put("componentType", "component_type");
    ballastlessLedgerColumnMap.put("status", "status");
    ballastlessLedgerColumnMap.put("delFlag", "del_flag");
    ballastlessLedgerColumnMap.put("createBy", "create_by");
    ballastlessLedgerColumnMap.put("createTime", "create_time");
    ballastlessLedgerColumnMap.put("updateBy", "update_by");
    ballastlessLedgerColumnMap.put("updateTime", "update_time");
    tableKeyColumnMap.put("BallastlessLedger", ballastlessLedgerColumnMap);

    ColumnUtil.VERSIONED_KEY_COLUMN_MAP.put(1, tableKeyColumnMap);

    // 初始化列工具
    ColumnUtil.init();

    // 调试:检查初始化结果
    System.out.println("映射配置初始化完成");
    System.out.println("表映射: " + ColumnUtil.VERSIONED_KEY_COLUMN_MAP.get(1).keySet());

}

@Override
public AbstractSQLConfig<String> setColumn(List<String> column) {
    System.out.println(ColumnUtil.VERSIONED_KEY_COLUMN_MAP);
    List<String> list = ColumnUtil.compatInputColumn(column, getTable(), getMethod(), 1, false);
    return super.setColumn(list);
}

@Override
public String getKey(String key) {
    System.out.println(ColumnUtil.VERSIONED_KEY_COLUMN_MAP);
    String inputKey = ColumnUtil.compatInputKey(key, getTable(), getMethod(),1,false);
    String string = super.getKey(inputKey);
    return string;
}

}

日志内容

Image Image

查询条件

{ "BallastlessLedger[]": { "count": 20, "page": 0, "BallastlessLedger": { "delFlag": "0", "@order": "createTime-" }, "query": 2 }, "total@": "/BallastlessLedger[]/total" }

异常日志

Caused by: java.sql.SQLSyntaxErrorException: (conn=3221599286) Unknown column 'delFlag' in 'where clause' If column exists but type cannot be identified (example 'select ? field1 from dual'). Use CAST function to solve this problem (example 'select CAST(? as integer) field1 from dual') at com.oceanbase.jdbc.internal.util.exceptions.ExceptionFactory.createException(ExceptionFactory.java:110) at com.oceanbase.jdbc.internal.util.exceptions.ExceptionFactory.create(ExceptionFactory.java:202) at com.oceanbase.jdbc.OceanBaseStatement.executeExceptionEpilogue(OceanBaseStatement.java:331) at com.oceanbase.jdbc.JDBC4PreparedStatement.executeInternal(JDBC4PreparedStatement.java:258) at com.oceanbase.jdbc.JDBC4PreparedStatement.execute(JDBC4PreparedStatement.java:172) at com.oceanbase.jdbc.JDBC4PreparedStatement.executeQuery(JDBC4PreparedStatement.java:186) at apijson.orm.AbstractSQLExecutor.executeQuery(AbstractSQLExecutor.java:1386) at apijson.orm.SQLExecutor.executeQuery(SQLExecutor.java:70)

hany5725 avatar Sep 14 '25 02:09 hany5725

@hany5725 应该是自定义的 TunnelSqlConfig 没注册导致字段配置没用上 https://github.com/Tencent/APIJSON/issues/363 https://github.com/Tencent/APIJSON/issues/812

TommyLemon avatar Sep 14 '25 11:09 TommyLemon

@TommyLemon 有进行正常的初始化配置

启动类主方法:

Image

这是我的APIJSONConfig配置:

public class ApiJsonConfig {

/**
 * 初始化APIJSON配置
 */
public static void initApiJsonConfig() {
    // 配置APIJSON创建器
    configureApiJsonCreator();

    // 配置Spring实例获取器
    configureInstanceGetter();

    // 配置JSON回调处理器
    configureJsonCallback();

    log.info("APIJSON配置初始化完成");
}

/**
 * 配置APIJSON创建器
 */
private static void configureApiJsonCreator() {
    APIJSONApplication.DEFAULT_APIJSON_CREATOR = new APIJSONCreator<String>() {

        @Override
        public Parser<String> createParser() {
            return new TunnelParser();
        }

        @Override
        public FunctionParser<Long> createFunctionParser() {
            return new TunnelFunctionParser();
        }

        @Override
        public Verifier<String> createVerifier() {
            return new TunnelVerifier();
        }

        @Override
        public SQLConfig<String> createSQLConfig() {
            return new TunnelSqlConfig();
        }

        @Override
        public SQLExecutor<String> createSQLExecutor() {
            return new TunnelSqlExecutor();
        }
    };
}

hany5725 avatar Sep 15 '25 01:09 hany5725

断点调试 setColumn 和 getKey,发下截屏,包含对应变量的值

TommyLemon avatar Sep 16 '25 13:09 TommyLemon

这是初始化的断点信息: Image

Image Image

查询条件: { "BallastlessLedger[]": { "count": 20, "page": 0, "BallastlessLedger": { "delFlag": "0", "@order": "createTime-" }, "query": 2 }, "total@": "/BallastlessLedger[]/total" }

查询的调试信息:

Image Image Image

错误日志: Image

表结构:

Image

hany5725 avatar Sep 24 '25 01:09 hany5725

断点 getClosestValue ,看看为啥对 keyColumnMap 返回了 null

TommyLemon avatar Sep 24 '25 16:09 TommyLemon

init方法时正常的,实际调用时候

项目初始化启动时 Image

在查询时 这三个静态变量都为空了

Image

hany5725 avatar Sep 25 '25 08:09 hany5725

@hany5725 应该是在某个地方把 VERSIONED_KEY_COLUMN_MAP 重置或键值对清空了导致。 把 VERSIONED_KEY_COLUMN_MAP 所有用到的代码都用 IDE 找出来, 尤其是 VERSIONED_KEY_COLUMN_MAP = , VERSIONED_KEY_COLUMN_MAP.clear , VERSIONED_KEY_COLUMN_MAP.put , VERSIONED_KEY_COLUMN_MAP.putAll 等能改变内部值的代码,都附带上下文发出来。

或者干脆去掉业务逻辑、数据库 URI 及账号密码 等敏感代码,只保留基础的能复现的 Demo 发出来源码 (压缩后应该可以粘贴到 issue 中,不行的话直接 GitHub 上新建一个 repo 来提交代码)

TommyLemon avatar Oct 09 '25 11:10 TommyLemon

tunnel - 副本.zip这是出现问题的项目以及sql文件

hany5725 avatar Oct 10 '25 03:10 hany5725