EclipseLink JPA` @ PreUpdate`调用不会持久化

时间:2009-12-09 22:55:14

标签: java jpa eclipselink

我在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());
    }
}

2 个答案:

答案 0 :(得分:6)

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

答案 1 :(得分:5)

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

  

默认情况下,日期或日历类型为 NOT 是可变的,如果需要在日期或日历上调用set方法,则必须将映射设置为@Mutable。 / p>      

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

所以,要么注释

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

或定义

<property name="eclipselink.temporal.mutable" value="true" />
persistence.xml中的