2016-04-20 7 views
1

In einer Tabelle meiner Postgresql db, habe ich 2 Spalten mit Standardwert.jOOQ Konverter legte implizit einen Wert beim Schreiben eines Datensatzes

Ich definiere einen Konverter für einen von ihnen in jOOQ Generatorkonfiguration.

Wenn ich die Funktion record.store() ausführen, wird der Standardwert für das Feld ohne Konverter gut verwendet, aber nicht für den anderen, der Null wird.

Ich nie explizit diese Felder festlegen, aber ich denke, dass record.changed (MY_OBJECT.FIELD) == True nach der Ausführung des Konverters.

Ich bin mir nicht sicher, dass dies das erwartete Verhalten ist. Ist es ein Fehler? Gibt es dafür einen Workaround?

Edit: Hier ist der Code verwendet

TimestampBinding.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); 
    } 
} 

TimestampConverter.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() 
); 

store Rekord

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

Das ist ein Fehler sehr wahrscheinlich ist. Können Sie möglicherweise Code anzeigen, um das Problem zu reproduzieren? –

+0

Ich habe gerade den Code hinzugefügt, danke im Voraus für Ihre Hilfe – Manu

Antwort

0

Dieses Verhalten ist "erwartet" und hat eine lange Geschichte in jOOQ. Die kurze Erklärung ist hier:

  • Ihre Spalt active sind NOT NULL, damit der Java-Wert null als der SQL-Wert DEFAULT interpretiert wird, unabhängig von der Record.changed() Flagge.
  • Ihre Spalt created_at NULL-Werte zugelassen, damit der Java-Wert null interpretiert wird
    • als der SQL-Wert DEFAULT zu sein, wenn Record.changed(CREATED_AT) == false
    • als den SQL-Wert NULL wenn Record.changed(CREATED_AT) == true

ist mit Ihr Anruf an DSLContext.newRecord(), Sie kopieren alle Werte von Ihrem user POJO in Sie r userRecord, einschließlich aller null Werte. jooq kann nicht zwischen null uninitalisierten Werten und null Werten unterscheiden, die explizit ... null sind.

In Ihrem speziellen Fall, die beste Lösung wäre, alle Spalten zu erklären NOT NULL (die ohnehin besser auf konzeptioneller Ebene ist):

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

Ich stimme mit Ihnen auf der konzeptionellen Ebene, also habe ich die created_at Spalte auf NOT NULL geändert, dennoch habe ich den folgenden Fehler: Null-Wert in Spalte "created_at" verletzt nicht-null Zwang. Denken Sie in diesem Fall, dass jOOQ die Spalte mit dem Nullwert der Abfrage entfernen sollte, damit sich postgresql auf den Standardwert auswirkt? – Manu

+0

Nicht sicher, dass ich in meinem vorherigen Kommentar klar war, aber in meinem letzten Test ist "created_at" NICHT NULL und das Java-Null wird nicht als DEFAULT interpretiert. Es bedeutet, dass das erwartete Verhalten in meinem Fall nicht respektiert wird. Irgendeine Idee ? – Manu

+0

Die Standardwerte sollten auf 'null' angewendet werden, wenn eine Spalte 'NOT NULL' ist. Aber nur in den neuesten Versionen. Welche Version verwendest du? –