繁体   English   中英

jOOQ 转换器在写入记录时隐式设置一个值

[英]jOOQ converter implicitly set a value when writing a record

在我的 postgresql 数据库表中,我有 2 列具有默认值。

我在 jOOQ 生成器配置中为其中之一定义了一个转换器。

当我执行函数record.store() 时,默认值很好地用于没有转换器的字段,但不适用于另一个变为空的字段。

我从未明确设置这些字段,但我猜在执行转换器后 record.changed(MY_OBJECT.FIELD) == true 。

我不确定这是预期的行为。 这是一个错误吗? 有解决方法吗?

编辑:这是使用的代码

时间戳绑定.java

public class TimestampBinding implements Binding<Timestamp, Instant> {

    private static final Converter<Timestamp, Instant> converter = new TimestampConverter();

    private final DefaultBinding<Timestamp, Instant> delegate = new DefaultBinding<> (converter());

    @Override
    public Converter<Timestamp, Instant> converter() { return converter; }

    @Override
    public void sql(BindingSQLContext<Instant> ctx) throws SQLException {
        delegate.sql(ctx);
    }

    @Override
    public void register(BindingRegisterContext<Instant> ctx) throws SQLException {
        delegate.register(ctx);
    }

    @Override
    public void set(BindingSetStatementContext<Instant> ctx) throws SQLException {
        delegate.set(ctx);
    }

    @Override
    public void set(BindingSetSQLOutputContext<Instant> ctx) throws SQLException {
        delegate.set(ctx);
    }

    @Override
    public void get(BindingGetResultSetContext<Instant> ctx) throws SQLException {
        delegate.get(ctx);
    }

    @Override
    public void get(BindingGetStatementContext<Instant> ctx) throws SQLException {
        delegate.get(ctx);
    }

    @Override
    public void get(BindingGetSQLInputContext<Instant> ctx) throws SQLException {
        delegate.get(ctx);
    }
}

时间戳转换器.java

public class TimestampConverter implements Converter<Timestamp, Instant> {
    @Override
    public Instant from(Timestamp ts) {
        return ts == null ? null : ts.toInstant();
    }
    @Override
    public Timestamp to(Instant instant) {
        return instant == null ? null : Timestamp.from(instant);
    }
    @Override
    public Class<Timestamp> fromType() { return Timestamp.class; }
    @Override
    public Class<Instant> toType() { return Instant.class; }
}

sql

CREATE TABLE user (
  id uuid PRIMARY KEY,
  active boolean NOT NULL DEFAULT false,
  created_at timestamptz DEFAULT now()
);

存储记录

user.setId(UUID.randomUUID());
UserRecord userRecord = DSL.using(conn, SQLDialect.POSTGRES_9_3)
                .newRecord(userTable.USER, user);
userRecord.store();

这种行为是“预期的”,在 jOOQ 中有着悠久的历史。 简短的解释在这里:

  • 您的列activeNOT NULL ,因此无论Record.changed()标志如何,Java 值null被解释为 SQL 值DEFAULT
  • 您的列created_at为空,因此解释了 Java 值null
    • 如果Record.changed(CREATED_AT) == false则作为 SQL 值DEFAULT
    • 如果Record.changed(CREATED_AT) == true则作为 SQL 值NULL

通过调用DSLContext.newRecord() ,您将所有值从您的user POJO 复制到您的userRecord ,包括所有null值。 jOOQ无法区分null被uninitalised值和null是明确...值null

在您的特定情况下,最好的解决方案是将所有列声明为NOT NULL (无论如何在概念级别上更好):

CREATE TABLE user (
  id uuid PRIMARY KEY,
  active boolean NOT NULL DEFAULT false,
  created_at timestamptz NOT NULL DEFAULT now()
);

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM