You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

JOOQ Converter/Binding未执行加密代码排查:PostgreSQL bytea列存储BigDecimal[][][]加密数据异常

问题根源:你绕开了JOOQ的执行流程

你的核心问题其实很清晰——你直接使用了原生JDBC的PreparedStatement执行插入,完全跳过了JOOQ的整个转换/绑定机制,这就导致你配置的EncryptionBinding根本没有被调用的机会。

JOOQ的Converter和Binding是深度集成在JOOQ自身的SQL执行链路里的,只有当你通过JOOQ生成的DAO、DSLContext等API来构建和执行SQL时,JOOQ才会在合适的节点触发这些绑定逻辑。而你手动获取Connection创建PreparedStatement的操作,已经脱离了JOOQ的管控,加密代码自然不会生效。

正确实现方式:改用JOOQ API执行操作

你需要调整代码,用JOOQ提供的方式来执行插入,这样才能让Binding生效:

方式1:用JOOQ DSL构建插入语句

假设你通过codegen生成了表对象MY_TABLE,对应列是MATRIX_COLUMN,可以这样写:

private Result executeInsert(BigDecimal[][][] valueToEncrypt) {
    try (Connection conn = config.connectionProvider().acquire()) {
        DSLContext dsl = DSL.using(conn, SQLDialect.POSTGRES);
        
        // 用JOOQ DSL构建插入,自动触发Binding的加密逻辑
        Result<?> result = dsl.insertInto(MY_TABLE)
            .set(MY_TABLE.MATRIX_COLUMN, valueToEncrypt)
            .returning()
            .fetch();
            
        return result;
    } catch (SQLException e) {
        throw new RuntimeException("插入失败", e);
    }
}

方式2:使用JOOQ生成的DAO类

如果已经生成了对应表的DAO(比如MyTableDao),直接调用DAO的方法更简洁:

private Result executeInsert(BigDecimal[][][] valueToEncrypt) {
    MyTableDao dao = new MyTableDao(config);
    MyTableRecord record = dao.newRecord();
    record.setMatrixColumn(valueToEncrypt);
    dao.insert(record);
    
    // 如果需要返回插入后的记录,可按需调整
    return dao.fetchByMatrixColumn(valueToEncrypt);
}
JOOQ Converter/Binding的执行时机解析

再帮你梳理下这些组件在JOOQ流程中的触发节点,避免以后踩坑:

  1. SQL构建阶段:Binding.sql()会被调用,用来生成匹配数据库类型的SQL占位符声明
  2. 参数设置阶段:Binding.set()触发,流程是:
    • 先调用converter().to(userObject),把你的BigDecimal[][][]转换成加密后的byte[]
    • 再将加密后的字节数组设置到JDBC的PreparedStatement中
  3. 结果读取阶段:Binding.get()触发,调用converter().from(databaseObject),把数据库存储的加密byte[]解密并转换成BigDecimal[][][]
额外代码优化建议

你的EncryptionBinding里有两个细节可以调整:

  1. 补充sql()方法的实现,确保生成正确的PostgreSQL bytea类型声明:
@Override
public void sql(BindingSQLContext<BigDecimal[][][]> ctx) throws SQLException {
    ctx.render().visit(DSL.val(ctx.convert(converter()).value(), SQLDataType.BYTEA));
}
  1. 修正register()方法的参数类型,和bytea列匹配:
@Override
public void register(BindingRegisterContext<BigDecimal[][][]> ctx) throws SQLException {
    ctx.statement().registerOutParameter(ctx.index(), Types.BINARY);
}

内容的提问来源于stack exchange,提问作者jban

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.04.30 18:22:48