Java 设置要由数据库生成的JPA时间戳列?
在我的SQL Server 2000数据库中,我有一个类型为Java 设置要由数据库生成的JPA时间戳列?,java,jpa,persistence,annotations,timestamp,Java,Jpa,Persistence,Annotations,Timestamp,在我的SQL Server 2000数据库中,我有一个类型为DATETIME的时间戳(在函数中而不是在数据类型中)列,名为lastpothed设置为getdate(),作为其默认值/绑定 我正在使用Netbeans 6.5生成的JPA实体类,并在代码中包含了这些类 @Basic(optional = false) @Column(name = "LastTouched") @Temporal(TemporalType.TIMESTAMP) private Date lastTouched; 但
DATETIME
的时间戳(在函数中而不是在数据类型中)列,名为lastpothed
设置为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)
,但这引发了一个异常,表示数据库不允许TIMESTAMP
列的null
值,而这在设计上是不允许的
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持久层。我通过将代码更改为
@Basic(optional = false)
@Column(name = "LastTouched", insertable = false, updatable = false)
@Temporal(TemporalType.TIMESTAMP)
private Date lastTouched;
因此,在生成SQL插入时,时间戳列被忽略。我不确定这是不是最好的办法。欢迎反馈。我意识到这有点晚了,但我已经成功地用
@Column(name="timestamp", columnDefinition="TIMESTAMP DEFAULT CURRENT_TIMESTAMP")
这也适用于
当前日期
和当前时间
。我在Oracle中使用JPA/Hibernate,所以YMMV。我使用JPA2.0和MySQL 5.5.10可以很好地实现这一点,因为我只关心最后一次修改行的情况。MySQL将在第一次插入时创建一个时间戳,并且每次对行调用UPDATE时都会创建一个时间戳。(注意:如果我关心更新是否真的进行了更改,这将是一个问题)
本例中的“timestamp”列类似于“last toucted”列`
下面的代码使用单独的列“version”进行乐观锁定
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”列,其中实体类中的属性类型为“Date”。这是因为Date生成的值小于毫秒,但MySQL没有存储毫秒,所以当它比较数据库中的值和“attached”时实体,它认为它们有不同的版本号)
:
我不认为每个数据库都有自动更新时间戳(例如Postgres)。所以我决定在代码中的任何地方手动更新这个字段。这将适用于每个数据库:
thingy.setLastTouched(new Date());
HibernateUtil.save(thingy);
使用触发器是有原因的,但对于大多数项目来说,这不是其中之一。触发器可以让您更深入地了解特定的数据库实现
MySQL 5.6.28(Ubuntu 15.10,OpenJDK 64位1.8.066)似乎非常宽容,不需要任何其他东西
@Column(name="LastTouched")
MySQL 5.7.9(CentOS 6,OpenJDK 64位1.8.072)仅适用于
@Column(name="LastTouched", insertable=false, updatable=false)
不是:
我的其他系统信息(在两种环境中相同)
- hibernate entitymanager 5.0.2
- hibernate验证程序5.2.2
- mysql连接器java 5.1.38
@Column(name = "transactionCreatedDate", nullable = false, updatable = false, insertable = false, columnDefinition = "TIMESTAMP DEFAULT CURRENT_TIMESTAMP")
添加
@CreationTimestamp
注释:
@CreationTimestamp
@Column(name="timestamp", nullable = false, updatable = false, insertable = false)
private Timestamp timestamp;
如果您使用
@DynamicInsert
标记实体,例如
@Entity
@DynamicInsert
@Table(name = "TABLE_NAME")
public class ClassName implements Serializable {
Hibernate将生成不带
null
值的SQL。然后数据库将插入自己的默认值。这确实会影响性能,请参见[Dynamic Insert][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;
}
我发布这篇文章是为了让人们在使用MySQL和Java Spring Boot JPA时寻找答案,就像@immanuelRocha说的,Spring中的@Column中只有太多@CreationTimeStamp,在MySQL中,将默认值设置为“CURRENT_TIMESTAMP” 在Spring中,只添加以下行:
@列(name=“插入日期”)
@CreationTimestamp
私人时间戳插入日期代码>如果您在Java 8和Hibernate 5或Spring Boot JPA中进行开发,则直接使用以下注释
在实体类中。Hibernate从VM获取当前时间戳,并将在数据库中插入日期和时间
public class YourEntity {
@Id
@GeneratedValue
private Long id;
private String name;
@CreationTimestamp
private LocalDateTime createdDateTime;
@UpdateTimestamp
private LocalDateTime updatedDateTime;
…
}
实际上,再仔细考虑一下,我想我需要更新这个专栏,因为当我更改专栏时,我需要通过Java来更新它。除非有办法在数据库端进行列更新。根据,触发器是我应该在这里使用的。其他类型(如LocalDateTime)如何?使用此解决方案,我在类路径资源[org/springframework/boot/autoconfigure/orm/jpa/hibernatejbaconfiguration.class]中定义了名为“entityManagerFactory”的bean,创建时出现错误:初始化方法调用失败;嵌套的异常是org.hibernate.AnnotationException:@Temporal应该只在java.util.Date或java.util.Calendar上设置
非常有用的信息,谢谢-我想很多人会因为升级到MySQL 5.7而被咬。x@James-谢谢,但我只是列出了我知道的差异。我不确定关键的区别是什么。它可能完全是另一回事。希望其他人能基于这个答案。是的,对不起,我应该补充一点,我在Ubuntu 14.04.1上从MySQL 5.6升级到5.7后遇到了这个错误(操作系统和JDK没有被修改)。所以我假设MySQL版本是这里的关键因素。@James-wow,这真的很有用。谢谢我已经更新了我的答案来反映这一点。这对我们很有效!我们将其与insertable=false,updateable=false
ERROR 4371-[main]org.hibernate.tool.hbm2ddl.SchemaExport结合使用:您的SQL语法有错误;检查与您的MySQL服务器版本对应的手册,以了解在第1行处使用的接近“
时间戳默认当前时间戳`not null,完整内容”
longtext not null”的正确语法。我的列是:
@column(nullable=false,name=“created_at”,updateable=false,columnDefinition=“TIMESTAMP DEFAULT CURRENT_TIMESTAMP”)`和private TIMESTAMP createdAt代码>这是一个简短的a
@CreationTimestamp
@Column(name="timestamp", nullable = false, updatable = false, insertable = false)
private Timestamp timestamp;
@Entity
@DynamicInsert
@Table(name = "TABLE_NAME")
public class ClassName implements Serializable {
@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;
}
public class YourEntity {
@Id
@GeneratedValue
private Long id;
private String name;
@CreationTimestamp
private LocalDateTime createdDateTime;
@UpdateTimestamp
private LocalDateTime updatedDateTime;
…
}