2017-02-22 19 views
0

我有一個具有創建日期和修改日期列的JPA實體。在創建/保留時,創建日期和修改日期都由數據庫中給出的默認值生成,該時間戳是時間戳。然而,創建工程,當我嘗試做更新/合併時,我不知道如何通過使用數據庫中的默認值來更改修改日期。有什麼建議?這是當前設置:JPA EntityManager - 使用合併生成默認值?

.... 
@Temporal(TemporalType.DATE) 
@Column(name="CREATED_DATE", insertable = false, updatable = false) 
private Date createdDate; 

@Temporal(TemporalType.DATE) 
@Column(name="MODIFIED_DATE", insertable = false) 
private Date modifiedDate; 
.... 

-

public Database changeDate(Database oldValues) 
    Database newvalues = new Database(); 
    .... 
    newValues.setCreatedDate(oldValues.getCreatedDate); 
    //newValues.setModifiedDate(); <-- (Should use the default value in the database) 
    .... 
    em.merge(newValues); <-- (EntityManager) 
    em.getTransaction().commit(); 

**萬一我沒有讓自己清楚,我只是不知道如何使它與默認值設置更新在數據庫中。

+0

只是爲了讓這個更清楚一點,你是說「我試圖更新newValues.modifiedDate到一個新的Date()值,但事務提交後,數據庫顯示沒有更新」或「我想更新newValues .modifiedDate爲空值,但我收到異常「? –

+0

我想嘗試將其更新爲其存儲在數據庫中的默認值。將它設置爲null沒有幫助。我可能會執行新的Date()路由,但我仍然更喜歡默認值。 –

+0

我會建議編輯你的問題,並刪除「null」。如果你重新解釋你的問題來準確地解釋你正在做的事情,那麼我們會更容易幫助你。 –

回答

0

有一個註釋,你可以使用javax.persistence.Version

@Column(name="CREATED_DATE", updatable = false) 
private java.sql.Timestamp createdDate = new java.sql.Timestamp(System.currentTimeMillis()); 

@Version 
@Column(name="MODIFIED_DATE") 
private java.sql.Timestamp modifiedDate; 

兩個領域只需要一個getter,不需要setter。 JPA將自行比較和更新時間戳值。否則,如果你依賴數據庫爲你生成它,你不妨試試@GeneratedValue(strategy = GenerationType.IDENTITY)或AUTO,但我確定它不適用於Hibernate。也許它可以在其他JPA提供商中使用。在Hibernate中,AUTO的值總是回落到SEQUENCE,所以這個策略沒有任何作用。

+0

這一個非常接近 - 唯一的問題是GeneratedValue註釋已被用於ID,顯然你只能每個實體有一個(也許我應該說這是一個開始,但我認爲這不會是一個大問題)。版本不允許輸入日期類型。我嘗試使用Timestamp來查看它是否可行,但是實體無法與數據庫匹配。 –

+0

如果您從數據庫中的值中截斷幾微秒(真的小於毫秒),則帶有時間戳的'@ Version'應該可以工作。在我們轉移到Java 8並切換到「Instant」之前,這就是我們不得不做的。 – coladict

+0

這似乎奏效了!非常感謝你! –

1

您要設置空值爲止。請在您的日期註釋中添加可爲空的屬性。它會工作。

它加入你的註釋可空=真

@Temporal(TemporalType.DATE) 
@Column(name="CREATED_DATE",nullable = true, insertable = false, updatable = false) 
private Date createdDate; 

@Temporal(TemporalType.DATE) 
@Column(name="MODIFIED_DATE", nullable = true, insertable = false) 
private Date modifiedDate; 
+0

在數據庫中,我將它設置爲修改日期不能爲空的值。有了註釋,它只是給了我同樣的錯誤。 - 該值不能設置爲空。我不認爲我在我的問題中明確表示過。對不起,關於這個:c –

+0

在數據庫中更改爲null。這將工作 –

0

如果我理解正確的問題,你想確保MODIFIED_DATE列總是被設置爲CURRENT_TIMESTAMP。然後,當數據庫實體更新並修改其他字段時,MODIFIED_DATE列將設置爲CURRENT_TIMESTAMP。

我假設你的數據庫表看起來是這樣的:

CREATE TABLE Database (
    ID int NOT NULL, 
    CREATED_DATE TIMESTAMP DEFAULT CURRENT_TIMESTAMP, 
    MODIFIED_DATE TIMESTAMP DEFAULT CURRENT_TIMESTAMP 
) 

你想要做的就是添加一個@PreUpdate方法到數據庫實體類和有它的modifiedDate屬性設置爲一個新的日期( ) 每一次。然後,無論何時對實體進行更新,MODIFIED_DATE列都將設置爲新的日期!

下面是一個例子:

@PreUpdate 
protected void onUpdate() { 
    modifiedDate = new Date(); 
} 

嘗試一個簡單的例子,看看它是如何工作的:

em.getTransaction().begin(); 
Database db = new Database(1, "First Value"); 
em.persist(db); 
em.getTransaction().commit(); 

em.getTransaction().begin(); 
Database db2 = em.find(Database.class, 1); 
db2.setValue("New Value!"); 
em.getTransaction().commit(); 
+0

所以基本上使用新的日期()路線 - 這似乎是我迄今唯一的選擇。 PreUpdate是一個相當不錯的功能,不知道它存在。 –

+0

@RaccoTaco問題是,使用數據庫表的默認功能僅用於插入NEW行。如果插入新行並且未能爲具有缺省值的列提供值,則使用缺省值使該值不爲NULL。在您的用例中,在將該值初始化爲默認值後,無需刪除該行並重新插入該行即可將其撤消。 –

+0

雖然這可能有效,但我警告它。總的來說,我認爲將這種業務邏輯放在數據庫上是一個糟糕的設計決定。另外,我的答案爲管理價值提供了更大的靈活性。依靠提供者或數據庫來設置值意味着手動更改值不是不可能或困難 –