2017-02-22 4 views
0

私は作成された日付と変更された日付の列を持つ1つの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()値に更新しようとしていますが、トランザクションコミット後にDBに更新が表示されません」または「newValuesを更新しようとしています.modifiedDateをnull値に設定していますが、例外が発生しています。 –

+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に使用されていて、エンティティごとに1つずつ(多分私はそのフォームを最初に言っておくべきでしたが、それは大きな問題ではないと思っていました)。また、Date型はバージョンでは使用できません。私はタイムスタンプを使用して、動作するかどうかを確認しようとしましたが、エンティティをデータベースと照合できませんでした。 –

+0

データベースの値からマイクロ秒(ミリ秒より短いもの)を切り捨てると、タイムスタンプ付きの '@ Version'が機能するはずです。 Java 8に移行して「即時」に切り替える前に、これを実行する必要がありました。 – coladict

+0

これはうまくいきました!どうもありがとうございました! –

1

Null値を現在に設定します。あなたの日付の注釈にnull可能なプロパティを追加してください。それが動作します。

あなたの注釈に真= NULL可能

@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

データベースでは、変更日をnull値にすることはできません。アノテーションを使用すると、同じエラーが表示されます。 - 値をnullに設定できないこと。私は私の質問でそれを明確にしたとは思わない。申し訳ありません:c –

+0

データベースのnullに変更してください。 –

0

をそれを追加私が正しく質問を理解していれば、あなたはMODIFIED_DATE列が常にCURRENT_TIMESTAMPに設定されることを確認します。次に、データベースエンティティが更新され、他のフィールドが変更されると、MODIFIED_DATE列はCURRENT_TIMESTAMPに設定されます。私はあなたのDBテーブルは次のようになりますことを前提としてい

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

が基本的に新しいDate()ルートを使用しているので、これまでのところ私の唯一の選択肢のようです。 PreUpdateは、それが存在していたかどうか分かりませんでした。 –

+0

@RaccoTaco問題は、DBテーブルのデフォルト機能を使用することは、新しい行を挿入するためだけであるということです。新しい行を挿入し、デフォルトの列の値を指定しなかった場合は、デフォルト値を使用して値がNULLにならないようにします。 usecaseでは、値がデフォルトに初期化された後、行を削除して再挿入しないと元に戻すことはできません。 –

+0

これはうまくいくかもしれませんが、私はそれに対して警告します。一般的に、このビジネスロジックをDBに組み込むのは設計上の決定が悪いと思う。また、私の答えはあなたの価値を管理するための柔軟性を提供します。プロバイダまたはDBに値を設定することは、値を手動で変更することが不可能または困難であることを意味します。 –

関連する問題