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

Jam*_*hon 56 java persistence timestamp annotations jpa

在我的SQL Server 2000数据库中,我有一个DATETIME名为lastTouchedset 的类型的时间戳(在函数中不在数据类型中)列getdate()作为其默认值/ binding.

我正在使用Netbeans 6.5生成的JPA实体类,并在我的代码中使用它

@Basic(optional = false)
@Column(name = "LastTouched")
@Temporal(TemporalType.TIMESTAMP)
private Date lastTouched;
Run Code Online (Sandbox Code Playgroud)

但是,当我尝试将对象放入数据库时​​,我得到了,

javax.persistence.PersistenceException: org.hibernate.PropertyValueException: not-null property references a null or transient value: com.generic.Stuff.lastTouched
Run Code Online (Sandbox Code Playgroud)

我已经尝试设置设置@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.
Run Code Online (Sandbox Code Playgroud)

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

Jam*_*hon 51

我通过将代码更改为修复了该问题

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

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

  • 根据http://stackoverflow.com/questions/36001/sql-server-2005-auto-updated-datetime-column-lastupdated,我应该在这里使用触发器。 (2认同)

Mat*_*ngo 39

我意识到这有点晚了,但我已经成功地用时间戳列注释了

@Column(name="timestamp", columnDefinition="TIMESTAMP DEFAULT CURRENT_TIMESTAMP")
Run Code Online (Sandbox Code Playgroud)

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

  • 这对我们有用!我们将它与`insertable = false,updatable = false`结合起来 (6认同)

ana*_*ule 13

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

\n
public class YourEntity {\n \n    @Id\n    @GeneratedValue\n    private Long id;\n \n    private String name;\n \n    @CreationTimestamp\n    private LocalDateTime createdDateTime;\n \n    @UpdateTimestamp\n    private LocalDateTime updatedDateTime;\n \n    \xe2\x80\xa6\n}\n
Run Code Online (Sandbox Code Playgroud)\n

  • https://docs.jboss.org/hibernate/orm/4.3/javadocs/org/hibernate/annotations/CreationTimestamp.html :属性值将设置为当前 VM 日期。这可能是也可能不是数据库系统设置的时间,具体取决于它们的时钟是否同步...在大多数情况下应该没问题,除非同步多个系统至关重要。 (3认同)

Dhw*_*tel 8

添加@CreationTimestamp注释:

@CreationTimestamp
@Column(name="timestamp", nullable = false, updatable = false, insertable = false)
private Timestamp timestamp;
Run Code Online (Sandbox Code Playgroud)


Gle*_*son 6

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

thingy.setLastTouched(new Date());
HibernateUtil.save(thingy);
Run Code Online (Sandbox Code Playgroud)

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

MySQL 5.6 .28(Ubuntu 15.10,OpenJDK 64位1.8.0_66)似乎非常宽容,不需要任何超越

@Column(name="LastTouched")
Run Code Online (Sandbox Code Playgroud)

MySQL 5.7 .9(CentOS 6、OpenJDK 64 位 1.8.0_72)仅适用于

@Column(name="LastTouched", insertable=false, updatable=false)
Run Code Online (Sandbox Code Playgroud)

不是:

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

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

  • 休眠实体管理器 5.0.2
  • 休眠验证器 5.2.2
  • mysql-连接器-java 5.1.38


max*_*mus 6

@Column(nullable = false, updatable = false)
@CreationTimestamp
private Date created_at;
Run Code Online (Sandbox Code Playgroud)

这对我有用。 更多信息

  • https://docs.jboss.org/hibernate/orm/4.3/javadocs/org/hibernate/annotations/CreationTimestamp.html :属性值将设置为当前 VM 日期。这可能是也可能不是数据库系统设置的时间,具体取决于它们的时钟是否同步...在大多数情况下应该没问题,除非同步多个系统至关重要。 (2认同)

wil*_*rdy 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;
}
Run Code Online (Sandbox Code Playgroud)

(注意:@Version 不适用于 MySQL 的“DATETIME”列,其中实体类中的属性类型为“Date”。这是因为 Date 生成了一个精确到毫秒的值,但是 MySQL 没有存储毫秒,所以当它比较数据库中的内容和“附加”实体时,它认为它们有不同的版本号)

从关于 TIMESTAMP 的 MySQL 手册

With neither DEFAULT nor ON UPDATE clauses, it is the same as DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP.
Run Code Online (Sandbox Code Playgroud)


pon*_*275 5

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

@Entity
@DynamicInsert
@Table(name = "TABLE_NAME")
public class ClassName implements Serializable  {
Run Code Online (Sandbox Code Playgroud)

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