78

私の SQL Server 2000 データベースには、デフォルト値/バインディングとして設定された型のタイムスタンプ (データ型ではなく関数内) 列がありDATETIMEます。lastTouchedgetdate()

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)許可していないという例外がスローされますが、これは設計上許可されていません。nullTIMESTAMP

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

以前はこれを純粋な Hibernate で動作させていましたが、その後 JPA に切り替えましたが、この列がデータベース側で生成されることになっていることを伝える方法がわかりません。JPA永続レイヤーとしてHibernateをまだ使用していることに注意してください。

4

12 に答える 12

67

コードを次のように変更して問題を修正しました

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

そのため、SQL 挿入を生成するときにタイムスタンプ列は無視されます。これが最善の方法であるかどうかはわかりません。フィードバックは大歓迎です。

于 2009-05-01T18:57:02.813 に答える
52

これは少し遅れていることに気づきましたが、タイムスタンプ列に注釈を付けることに成功しました

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

これは と で動作するはずCURRENT_DATEですCURRENT_TIME。JPA/Hibernate with Oracle を使用しているので、YMMV です。

于 2010-06-24T06:20:15.483 に答える
23
@Column(nullable = false, updatable = false)
@CreationTimestamp
private Date created_at;

これは私のために働いた。 より詳しい情報

于 2017-12-29T09:27:50.570 に答える
5

行が最後に変更されたときだけを気にする場合、JPA2.0 と MySQL 5.5.10 を使用してこれをうまく機能させています。MySQL は、最初の挿入時にタイムスタンプを作成し、UPDATE が行に対して呼び出されるたびに作成します。(注:UPDATEが実際に変更を加えたかどうかを気にした場合、これは問題になります)。

この例の「タイムスタンプ」列は、「最後に触れた」列のようなものです.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 は、Entity クラスの属性タイプが「Date」である MySQL の「DATETIME」列では機能しません。これは、Date がミリ秒までの値を生成していたためでしたが、MySQL はミリ秒を格納していませんでした。 、したがって、データベースにあるものと「添付された」エンティティを比較すると、バージョン番号が異なると見なされました)

TIMESTAMP に関する MySQL マニュアルから:

With neither DEFAULT nor ON UPDATE clauses, it is the same as DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP.
于 2011-04-28T03:22:26.023 に答える
4

すべてのデータベースに自動更新タイムスタンプがあるとは思いません (Postgres など)。そこで、このフィールドをコードのどこでも手動で更新することにしました。これはすべてのデータベースで機能します。

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

トリガーを使用する理由はいくつかありますが、ほとんどのプロジェクトでは、これは理由の 1 つではありません。トリガーは、特定のデータベースの実装をさらに深く掘り下げます。

MySQL 5.6 .28 (Ubuntu 15.10、OpenJDK 64-Bit 1.8.0_66) は非常に寛容なようで、それ以上のものは必要ありません。

@Column(name="LastTouched")

MySQL 5.7 .9 (CentOS 6、OpenJDK 64 ビット 1.8.0_72) のみで動作します

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

いいえ:

FAILED: removing @Temporal
FAILED: @Column(name="LastTouched", nullable=true)
FAILED: @Column(name="LastTouched", columnDefinition="TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP")

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

  • 休止状態エンティティマネージャー 5.0.2
  • 休止状態バリデーター 5.2.2
  • mysql-connector-java 5.1.38
于 2016-02-15T19:49:37.033 に答える
3

@immanuelRochaが言うように、MySQLとJava Spring Boot JPAを使用するときに答えを探している人のためにこれを投稿しています.Springの@Columnには@CreationTimeStampしかなく、MySQLではデフォルト値を "CURRENT_TIMESTAMP"

Spring では、次の行だけを追加します。

@Column(name = "insert_date")
@CreationTimestamp
private Timestamp insert_date;

于 2020-03-09T17:47:48.760 に答える