2014-10-28 21 views
5

Tôi có một vấn đề khá đơn giản. Trong một giao dịch duy nhất, mã của tôi trông giống như sau:Dữ liệu Spring JPA JpaRepository.save (thực thể) không trả lại giá trị mặc định của cơ sở dữ liệu

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

c = myClassRepository.save(c); 

c.setPropC("C"); 

đâu thực thể của tôi trông như thế này:

@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; } 
} 

Và cơ sở dữ liệu được thiết lập như thế này (Dialect = Oracle 11G)

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

Vì vậy, dựa trên mã để duy trì thực thể, tôi cho rằng tôi sẽ nhận được các truy vấn giống như sau:

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" 

... nhưng SELECT không bao giờ xảy ra. Tại sao thực thể không được làm mới?

Điều này vi phạm vì số UPDATE rằng (ngay) theo sau INSERTc.propB vẫn là null. Tôi nhận được dấu vết ngăn xếp ORA-01407: cannot update ("MY_SCHEMA"."MY_CLASS"."PROP_B") to NULL.

Tôi nhận ra có nhiều cách xung quanh việc này bằng cách sử dụng @PrePersist hoặc đặt giá trị mặc định trên columnDefinition bằng Java, nhưng tôi không phải đặt mặc định trùng lặp.

Lưu ý: Tính năng này hoạt động trước khi tôi sử dụng org.hibernate.Session.saveOrUpdate() thay vì JPA dữ liệu mùa xuân cho hành động này.

Cảm ơn bạn đã giúp đỡ!

Trả lời

4

Hibernate không biết rằng B được tạo ra bởi cơ sở dữ liệu, và nó phải đọc nó sau khi chèn, trừ khi bạn yêu cầu nó làm như vậy bằng cách sử dụng @Generated annotation.

+0

Tốt bắt! '@ GeneratedValue' có phải là tương đương JPA không? – Andy

+0

Trong trường hợp của tôi, tôi có một cột 'modified_at' và giá trị mặc định là datetime hiện tại. Điều duy nhất hiệu quả với tôi là [@UpdateTimestamp] (https://docs.jboss.org/hibernate/orm/4.3/javadocs/org/hibernate/annotations/UpdateTimestamp.html). Tôi không cần phải gọi '.flush()'. Không phải [@Generated] (http://docs.jboss.org/hibernate/orm/4.3/javadocs/org/hibernate/annotations/Generated.html) hoặc [@GeneratedValue] (http://docs.oracle. com/javaee/5/api/javax/persistence/GeneratedValue.html) chú thích làm việc cho tôi, ngay cả sau khi sử dụng '.flush()' trường sẽ vẫn trở lại như null sau khi một '.save()'. – Doug

Các vấn đề liên quan