2009-05-01 15 views
43

私のSQL Server 2000データベースでは、lastTouchedという名前のタイプDATETIMEのタイムスタンプ(データ型ではない)カラムがデフォルト値/バインディングとしてgetdate()に設定されています。データベースによって生成されるJPAタイムスタンプ列を設定しますか?

私はNetbeansの6.5生成されたJPAエンティティークラスを使用して、私は私が手にデータベースにオブジェクトを配置しようとするときしかし、私のコード

@Basic(optional = false) 
@Column(name = "LastTouched") 
@Temporal(TemporalType.TIMESTAMP) 
private Date lastTouched; 

でこれを持って、

javax.persistence.PersistenceException: org.hibernate.PropertyValueException: not-null property references a null or transient value: com.generic.Stuff.lastTouched 

@Basic(optional = true)に設定しようとしましたが、データベースでnullの値がTIMESTAMPの列を使用できないという例外がスローされます。

ERROR JDBCExceptionReporter - Cannot insert the value NULL into column 'LastTouched', table 'DatabaseName.dbo.Stuff'; column does not allow nulls. INSERT fails. 

私は以前、これは純粋な休止状態で動作するようになったが、私はセンスがJPAに切り替えると、この列は、データベース側で生成されると仮定されていること、それを伝えるためにどのよう見当がつかないています。私はまだJPA永続性レイヤーとしてHibernateを使用しています。

答えて

42

私はSQLの挿入を生成するときにタイムスタンプ列が無視され

@Basic(optional = false) 
@Column(name = "LastTouched", insertable = false, updatable = false) 
@Temporal(TemporalType.TIMESTAMP) 
private Date lastTouched; 

にコードを変更することで問題を修正しました。これが最善の方法であるかどうかはわかりません。フィードバックは大歓迎です。

+5

あなたは、データベースを使用するように @Column(名前= "LastTouched" 偽=挿入可能、偽=更新可能) を追加することができますは、SQL UPDATE文でも、タイムスタンプを生成しました。 –

+0

Juhaに感謝します。私はそれが後に道を邪魔したと確信しています。 –

+0

実際、もっと考えてみると、更新時に列が必要になると思います。なぜなら、列の変更を行うときにJavaで更新する必要があるからです。何らかの形でデータベース側で列の更新を行う方法がない限り。 –

27

私は、これは少し遅れている実感が、私はこれもCURRENT_DATECURRENT_TIMEで動作するはずです

@Column(name="timestamp", columnDefinition="TIMESTAMP DEFAULT CURRENT_TIMESTAMP") 

とタイムスタンプ列に注釈を付けると成功を収めてきました。私はJPA/HibernateをOracleと併用しているので、YMMVです。

+5

これは私たちのために働いた!これを 'insertable = false、updatable = false'と組み合わせました。 –

+0

' ERROR 4371 --- [main] org.hibernate.tool.hbm2ddl.SchemaExport:SQL構文に誤りがあります。あなたのMySQLサーバのバージョンに対応するマニュアルを見て、正しい文法については、 '' TIMESTAMP DEFAULT CURRENT_TIMESTAMP' not null、 'full_content' longtext near line 'on line 1'の近くで使用するようにしてください。私の列は: '@Column(nullable = false、name =" created_at "、updatable = false、columnDefinition =" TIMESTAMP DEFAULT CURRENT_TIMESTAMP ")'と 'private Timestamp createdAt; –

3

JPA2.0とMySQL 5.5.10を使用して、この行が正常に処理されたのは、最後に行が変更されたときだけです。 MySQLは最初の挿入時にタイムスタンプを作成し、その行でUPDATEが呼び出されるたびにタイムスタンプを作成します。 (注意:これは、UPDATEが実際に変更されたかどうかを気にすると問題になります)。

この例では「タイムスタンプ」列には、「最後にタッチ」column.x`

以下のコードは、楽観的ロックのために別の列「バージョン」を使用するようなものです。

private long version; 
private Date timeStamp 

@Version 
public long getVersion() { 
    return version; 
} 

public void setVersion(long version) { 
    this.version = version; 
} 

// columnDefinition could simply be = "TIMESTAMP", as the other settings are the MySQL default 
@Column(name="timeStamp", columnDefinition="TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP") 
@Temporal(TemporalType.TIMESTAMP) 
public Date getTimeStamp() { 
    return timeStamp; 
} 

public void setTimeStamp(Date timeStamp) { 
    this.timeStamp = timeStamp; 
} 

は(注:@Versionは、属性の型がエンティティクラスの「日」であるMySQLの「DATETIME」列、上では動作しません日付をミリ秒までの値を生成していましたので、これがありました。しかし、MySQLはミリ秒を格納していなかったので、それは「添付」エンティティデータベースにあった、と何の間の比較をしたとき、それは彼らが異なるバージョン番号)

From the MySQL manual regarding TIMESTAMP思っていた:

With neither DEFAULT nor ON UPDATE clauses, it is the same as DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP. 
0

IをJPA 2.0とMySを使ってうまく動作しますQL 5.5.10。

私はこのようなTimesampフィールドを挿入:

@Column(name = "LastTouched") 
private Timestamp lastTouched; 
2

私は、すべてのデータベースが自動更新のタイムスタンプ(例えば、Postgresのを)持っているとは思いません。だから、私は自分のコードのどこにでもこのフィールドを手動で更新することに決めました。これはすべてのデータベースで動作します:

thingy.setLastTouched(new Date()); 
HibernateUtil.save(thingy); 

トリガーを使用する理由はありますが、ほとんどのプロジェクトではこれはその1つではありません。トリガーは、特定のデータベースの実装をより深く理解します。

のMySQL 5.6 0.28(Ubuntuの15.10、OpenJDKの64ビット1.8.0_66)が

@Column(name="LastTouched") 

のMySQL 5.7 0.9(CentOSの6、OpenJDKのを超えて何かを必要としない、非常に寛容であるように思わ

FAILED: removing @Temporal 
FAILED: @Column(name="LastTouched", nullable=true) 
FAILED: @Column(name="LastTouched", columnDefinition="TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP") 
:64ビット1.8.0_72)が唯一

@Column(name="LastTouched", insertable=false, updatable=false) 

ないで動作します

私の他のシステム情報(両方の環境で同じ)

  • 休止-のEntityManager 5.0.2
  • 休止-バリ5.2.2
  • のmysql-コネクタ-javaの5.1.38
+0

非常に有益な情報、ありがとう人々はこのMySQL 5.7.xへのアップグレードによって噛まれるでしょう – James

+0

@James - ありがとう、しかし私はちょうど私が知っていた違いを挙げました。私はクリティカルな違いが何であるかは分かりません。それはまったく別のものかもしれません。うまくいけば、誰かがこの答えを築くことができればと思います – GlenPeterson

+1

はい、残念ですが、私は、MySQL 5.6からUbuntu 14.04.1(OSとJDKはAFAIKに変更されていません)で5.7にアップグレードした後、このエラーが発生したと付け加えておきます。だから私はMySQLバージョンがここで重要な要素であると仮定していた。 – James

2
@Column(nullable = false, updatable = false) 
@CreationTimestamp 
private Date created_at; 

これは私のために働いた。 more info

関連する問題