10

我在 StackOverflow 上遇到了一些类似的问题,尝试了解决方案,但没有找到答案。

我正在使用一种相当常见的 JPA 策略来设置某些实体的最后修改时间。设置列和字段,然后标记一个方法@PreUpdate并让它设置它们等于当前时间。

问题是我可以在调试器中看到正在调用该方法并且正在更新该字段,但是在我的数据库日志中我只看到一个 SQL 调用来更新不包括时间戳字段的 UPDATE 已更改字段.

使事情进一步复杂化@PrePersist非常有效,只会@PreUpdate表现出这种行为。

到目前为止,我发现的最接近的解释是在这个LINK

类似问题:#1725699 和 #1745890

我正在使用 EclipseLink v2 和 JPA v1 来与 GlassFish v2 兼容。

我尝试直接在 Entity 类中的方法上使用这两个注释,以及使用注释EntityListener附加到 Entity 类@EntityListener

我怀疑这是 EclipseLink 中的一个错误,但我无法证明这一点。

错误与否我非常希望这个简单的操作能够工作。这个实现有什么问题吗?这是 EclipseLink 中的一个已知问题吗?这是 JPA 中的一个已知问题吗?有没有解决的办法?

如果没有访问数据库并使用触发器,是否有替代路径让我的 Java 代码设置 updated_on 时间戳?

感谢您的建议!

代码片段如下。

实体字段:

@Column(name = "updated_on")
@Temporal(TemporalType.TIMESTAMP)
private Date updatedOn;
@Column(name = "created_on")
@Temporal(TemporalType.TIMESTAMP)
private Date createdOn;

带注释的更新方法:

@PreUpdate
public void setUpdatedOn(Timestamped object) {
    object.setUpdatedOn(new Date());
}

@PrePersist
public void setCreatedOn(Timestamped object) {
    if (object.getCreatedOn()==null) {
      object.setCreatedOn(new Date());
    }
}
4

2 回答 2

7

您提供的链接准确描述了您的情况:对于脏检查,在调用 @PreUpdate 方法之前检测到更新的字段,并且不再检测到 @PreUpdate 方法中的更改。这可能是出于性能原因,因为脏检查在大型对象图上可能非常昂贵。现在看来,您的选择是使用特定于提供程序的机制 (DescriptorEvent) 或切换到 Hibernate。

于 2009-12-09T23:16:55.200 回答
5

Mybe 有点晚了,但为了信息的完整性,这不是错误,而是记录在案的行为:

默认情况下, Date 或 Calendar 类型假定不可变,如果希望调用 Date 或 Calendar 上的 set 方法,则必须将映射设置为 @Mutable。

对于 Date 和 Calendar 类型,全局持久性属性“eclipselink.temporal.mutable”也可以设置为“true”。

所以,要么注释

@Mutable
@Column(name = "updated_on")
@Temporal(TemporalType.TIMESTAMP)
private Date updatedOn;

或定义

<property name="eclipselink.temporal.mutable" value="true" />

在persistence.xml中

于 2015-02-15T11:55:00.630 回答