设置由数据库生成的JPA时间戳列?

时间:2009-05-01 15:20:07

标签: java jpa persistence annotations timestamp

在我的SQL Server 2000数据库中,我有一个时间戳(在函数中不在数据类型中)列DATETIME,名为lastTouched,设置为getdate()作为其默认值/绑定。

我正在使用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.

我以前在纯Hibernate中使用它,但我有意识切换到JPA并且不知道如何告诉它该列假设在数据库端生成。请注意,我仍然使用Hibernate作为我的JPA持久层。

12 个答案:

答案 0 :(得分:50)

我通过将代码更改为

来解决了这个问题
@Basic(optional = false)
@Column(name = "LastTouched", insertable = false, updatable = false)
@Temporal(TemporalType.TIMESTAMP)
private Date lastTouched;

因此,生成SQL插入时会忽略timestamp列。不确定这是否是解决此问题的最佳方式。欢迎提供反馈。

答案 1 :(得分:34)

我意识到这有点晚了,但我已成功用

注释时间戳列
@Column(name="timestamp", columnDefinition="TIMESTAMP DEFAULT CURRENT_TIMESTAMP")

这也适用于CURRENT_DATECURRENT_TIME。我正在使用JPA / Hibernate和Oracle,所以YMMV。

答案 2 :(得分:6)

@Column(nullable = false, updatable = false)
@CreationTimestamp
private Date created_at;
这对我有用。 more info

答案 3 :(得分:4)

我使用JPA2.0和MySQL 5.5.10运行良好,我只关心上次修改行的情况。 MySQL将在第一次插入时创建时间戳,并且每次在行上调用UPDATE时。 (注意:如果我关心UPDATE是否实际发生了变化,这将是有问题的。)

此示例中的“timestamp”列类似于“last-touching”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”列,其中Entity类中的属性类型为“Date”。这是因为Date生成的值低至毫秒,但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.

答案 4 :(得分:4)

我不认为每个数据库都有自动更新时间戳(例如Postgres)。所以我决定在我的代码中手动更新此字段。这适用于每个数据库:

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

有理由使用触发器,但对于大多数项目,这不是其中之一。触发器可以让您更深入地了解特定的数据库实现。

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-Bit 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")

我的其他系统信息(两种环境都相同)

  • hibernate-entitymanager 5.0.2
  • hibernate-validator 5.2.2
  • mysql-connector-java 5.1.38

答案 5 :(得分:3)

我将其发布给使用MySQL和Java Spring Boot JPA时寻找答案的人们,例如@immanuelRocha所说,在Spring中也只有@CreationTimeStamp到@Column,并且在MySQL中将默认值设置为“ CURRENT_TIMESTAMP” “。

在Spring中仅添加以下行:

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

答案 6 :(得分:2)

如果您用@DynamicInsert标记您的实体,例如

@Entity
@DynamicInsert
@Table(name = "TABLE_NAME")
public class ClassName implements Serializable  {

Hibernate将生成不包含null值的SQL。然后数据库将插入其自己的默认值。这确实会对性能产生影响,请参见[动态插入] [1]。

答案 7 :(得分:1)

添加@CreationTimestamp批注:

@CreationTimestamp
@Column(name="timestamp", nullable = false, updatable = false, insertable = false)
private Timestamp timestamp;

答案 8 :(得分:1)

这也对我有用:-

@Temporal(TemporalType.TIMESTAMP)   
@Column(name = "CREATE_DATE_TIME", nullable = false, updatable = false, insertable = false, columnDefinition = "TIMESTAMP DEFAULT CURRENT_TIMESTAMP")
public Date getCreateDateTime() {
    return createDateTime;
}

public void setCreateDateTime(Date createDateTime) {
    this.createDateTime = createDateTime;
}

答案 9 :(得分:0)

@Column(name = "LastTouched", insertable = false, updatable = false, columnDefinition = "TIMESTAMP default getdate()")
@Temporal(TemporalType.TIMESTAMP)
private Date LastTouched;`enter code here`

答案 10 :(得分:0)

如果您正在使用 Java 8和Hibernate 5或Spring Boot JPA 进行开发,请直接使用以下注释 在您的Entity类中。 Hibernate从VM获取当前时间戳,并将日期和时间插入数据库。

public class YourEntity {
 
    @Id
    @GeneratedValue
    private Long id;
 
    private String name;
 
    @CreationTimestamp
    private LocalDateTime createdDateTime;
 
    @UpdateTimestamp
    private LocalDateTime updatedDateTime;
 
    …
}

答案 11 :(得分:-1)

这对我有用:

@Column(name = "transactionCreatedDate", nullable = false, updatable = false, insertable = false, columnDefinition = "TIMESTAMP DEFAULT CURRENT_TIMESTAMP")