2014-10-28 1 views
5

Ich habe ein ziemlich einfaches Problem. In einer einzigen Transaktion, sieht mein Code so etwas wie dieses:Spring Data JPA JpaRepository.save (Entität) gibt nicht die Standardwerte der Datenbank

MyClass c = new MyClass(); 
c.setPropA("A"); 

c = myClassRepository.save(c); 

c.setPropC("C"); 

Wo ist mein Unternehmen wie folgt aussieht:

@Entity 
@Table(name = "MY_CLASS") 
public class MyClass { 
    private String propA; 
    private String propB; 
    private String propC; 

    @Id 
    @Column(name = "PROP_A", unique = true, nullable = false, updatable = false) 
    public String getPropA() { return propA; } 
    public void setPropA(String propA) { this.propA = propA; } 

    @Column(name = "PROP_B", insertable = false) 
    public String getPropB() { return propB; } 
    public void setPropB(String propB) { this.propB = propB; } 

    @Column(name = "PROP_C") 
    public String getPropC() { return propC; } 
    public void setPropC(String propC) { this.propC = propC; } 
} 

und die Datenbank eingerichtet ist, wie diese (Dialect = Oracle 11G)

CREATE TABLE MY_CLASS { 
    PROP_A VARCHAR2 NOT NULL PRIMARY KEY, 
    PROP_B VARCHAR2 DEFAULT 'B' NOT NULL, 
    PROP_C VARCHAR2 
} 

So, basierend auf dem Code der Einheit bestehen bleiben, ich denke, ich würde Abfragen, die wie folgt aussehen bekäme:

MyClass c = new MyClass(); 
c.setPropA("A"); 

c = myClassRepository.saveAndFlush(c); 
// INSERT INTO MY_CLASS (PROP_A, PROP_C) VALUES ("A", NULL) 
// SELECT PROP_A, PROP_B, PROP_C FROM MY_CLASS -- to refresh `c` 

c.setPropC("C"); 

// After transaction ends, flush change to `c.propC` 
// UPDATE MY_CLASS SET PROP_B = "B", PROP_C = "C" WHERE PROP_A = "A" 

... aber die SELECT passiert nie. Warum wird die Entität nicht aktualisiert?

Dies bricht wegen der UPDATE, die (unmittelbar) folgt dem INSERT und c.propB ist noch null. Ich bekomme einen ORA-01407: cannot update ("MY_SCHEMA"."MY_CLASS"."PROP_B") to NULL Stack-Trace.

Ich weiß, es gibt Möglichkeiten, um dies mit @PrePersist oder Standardwerte setzen auf columnDefinition in Java, aber ich sollte nicht standardmäßig zu duplizieren.

Hinweis: Dies funktionierte vorher, als ich org.hibernate.Session.saveOrUpdate() anstelle von Spring Data JPA für diese Aktion verwendete.

Vielen Dank im Voraus für jede Hilfe!

Antwort

4

Hibernate weiß nicht, dass B von der Datenbank generiert wird und dass es nach dem Einfügen gelesen werden muss, es sei denn, Sie weisen es mithilfe der @Generated annotation an.

+0

Guter Fang! Wäre '@ GeneratedValue' das JPA-Äquivalent? – Andy

+0

In meinem Fall habe ich eine Spalte "Modified_at" und der Standardwert ist aktuelle Datetime. Das einzige, was für mich funktionierte, war [@UpdateTimestamp] (https://docs.jboss.org/hibernate/orm/4.3/javadocs/org/hibernate/annotations/UpdateTimestamp.html). Ich musste '.flush()' nicht aufrufen. Weder [@Generated] (http://docs.jboss.org/hibernate/orm/4.3/javadocs/org/hibernate/annotations/Generated.html) oder [@GeneratedValue] (http://docs.oracle. com/javaee/5/api/javax/persistence/GeneratedValue.html) Anmerkungen funktionierten für mich, selbst nach der Verwendung von '.flush()' würde das Feld nach einem '.save()' immernoch als null zurückkommen. – Doug

Verwandte Themen