当关联的数据库服务器和应用程序服务器在不同的时区运行时,检索,保留和更新应用程序服务器的当前时刻不是一个好方法。应始终询问数据库服务器以代替应用程序服务器的当前时间。
因此,在中间层JPA本身执行以下操作将是一种错误的方法。
Entity entity = new Entity();
entity.setTimestamp(new Timestamp(new java.util.Date().getTime()));
// Persist or merge the entity.
或者
Entity entity = new Entity();
entity.setLocalDateTime(java.time.LocalDateTime.now(ZoneOffset.UTC));
// Persist or merge the entity.
或者
Entity entity = new Entity();
entity.setZonedDateTime(java.time.ZonedDateTime.now(ZoneOffset.UTC));
// Persist or merge the entity.
或者
Entity entity = new Entity();
entity.setDateTime(org.joda.time.DateTime.now(org.joda.time.DateTime.DateTimeZone.UTC));
// Persist or merge the entity.
对于实体中的相应字段,等以及insertable = false, updatable = false
。
JPA允许从数据库服务器检索日期时间/时间戳。
javax.persistence.criteria.CriteriaBuilder#Expression<Date> currentDate()
javax.persistence.criteria.CriteriaBuilder#Expression<Time> currentTime()
javax.persistence.criteria.CriteriaBuilder#Expression<Timestamp> currentTimestamp()
当然,JPQL也是如此。
但是,JPA似乎无法通过委派持久化并将当前时间合并到数据库服务器本身的任务来持久化并合并数据库服务器本身的当前时间。
我对使用@Version
装饰日期时间相关字段不感兴趣,因为它在中间层JPA本身中获取行级乐观锁的目的完全不同(使用时间戳本身的乐观锁定也会受到影响从某些特殊的缺点)。
在中间层使用持久性提供程序时,我没有太多考虑RDBMS的丛林。
因此,除了像CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP
这样遵循RDBMS的功能之外,JPA或特定的持久性提供程序本身是否有办法处理数据库服务器的两个幂等操作的当前时间,即&#34;坚持&#34;和&#34;合并&#34;?
我目前关注的是Hibernate和EclipseLink。
答案 0 :(得分:0)
我遇到了同样的问题并在两个地方解决了。
1)在Oracle表格中,我已将默认值添加到SYSTIMESTAMP
"CREATION_DATE" TIMESTAMP (6) DEFAULT SYSTIMESTAMP
使用SYSTIMESTAMP
而非CURRENT_TIMESTAMP
或LOCALTIMESTAMP
非常重要,因为他们都会使用来电者会话的语言环境!
2)在Entity类中,对于永远不应更新的列我已经使用过:
@Column(name = "CREATION_DATE", insertable=false, updatable = false)
public Timestamp getCreationDate()
{
return creationDate;
}
通过这样做,生成的INSERT
查询不会包含Timestamp列,因此数据库使用默认的SYSTIMESTAMP
值。
对于可以更新的列,比如LAST_UPDATE
列,我想避免使用触发器,因此我必须在Spring Data中编写自定义查询:
<强> DB 强>
"LAST_UPDATE" TIMESTAMP (6) DEFAULT SYSTIMESTAMP
<强>实体强>
@Column(name = "LAST_UPDATE", insertable=false, updatable = true)
public Timestamp getLastUpdate()
{
return lastUpdate;
}
...
Spring Data Repository
@Modifying
@Query(value="update User u set u.lastUpdate=SYSTIMESTAMP where u.id=:userId")
void setLastUpdateTime(@Param("userId") int userId);
此解决方案不依赖于数据库,但避免使用触发器并同步Web服务器时间。