触发器与JPA @PrePersist创建和更新时间戳的优缺点

ams*_*ams 9 java postgresql hibernate jpa jpa-2.0

我正在构建一个新的Web应用程序,我正在使用Spring,JPA/Hibernate和Postgres.我的一些表有creation_ts和lastupdate_ts列,这些列是时间戳列,用于跟踪插入发生的时间以及行上次更新的时间.

我也在我的表中使用列的命名约定,因此在设计策略方面,每个表都保证有两列pkey,它是一个整数代理键,以及用于乐观锁定的版本.

我有两种方法可以使这些字段保持最新状态.

选项A:使用触发器

这是我现在已经采用的解决方案,我有两个Postgres触发器,可以触发插入和更新,并使这些字段保持最新.我有两节课.

@MappedSuperclass
public abstract class PersistableObject
{
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    @Column(name="pkey")
    private Integer pkey;

    @Version
    @Column(name="version")
    private Integer version;

    public Integer getPkey()
    {
        return this.pkey;
    }

    public Integer getVersion()
    {
        return this.version;
    }
}
Run Code Online (Sandbox Code Playgroud)

我有

@MappedSuperclass
public class TimeStampedPersistableObject extends PersistableObject {

    @Column(name = "creation_ts")
    @Temporal(TemporalType.DATE)
    @org.hibernate.annotations.Generated(value = GenerationTime.INSERT)
    private Date    creationTimestamp;

    @Column(name = "update_ts")
    @Temporal(TemporalType.DATE)
    @org.hibernate.annotations.Generated(value = GenerationTime.ALWAYS)
    private Date    updateTimestamp;

    public Date getCreationTimestamp()
    {
        return this.creationTimestamp;
    }

    public Date getUpdateTimestamp()
    {
        return this.updateTimestamp;
    }
}
Run Code Online (Sandbox Code Playgroud)

选项B:使用JPA监听器

在这个选项中,我将使用JPA监听器来使时间戳列保持最新.

我的问题:

这两种方法中的哪一种更好?我在这里看到的是我个人的每个选项的优缺点列表,我非常有兴趣听取其他人选择这两种选择的经验.

选项A专业人士:

  1. 数据库正在使用触发器进行更新,因此在运行Web应用程序的集群中不存在时钟偏差的危险.
  2. 如果非JPA应用程序访问数据库,则强制执行保留这两列的要求.

选项A缺点:

  1. 在插入和更新之后必须执行选择以读取触发器到位的值.
  2. 我正在使用hibernate注释来回读值

选项B专业人员:

  1. 创建DDL时输入较少
  2. 插入和更新后无需从数据库中读回值
  3. 纯JPA注释没有hibernate特定的注释

选项B缺点:

  1. 群集中时钟偏差的危险
  2. 每当JPA提供程序决定调用不可预测的回调方法时设置的字段

如何为新应用程序解决此问题,您可以完全控制数据库和Java代码.

a_h*_*ame 6

在插入和更新之后必须执行选择以读取触发器到位的值.

您可以使用INSERT ... RETURNINGUPDATE ... RETURNING检索触发器更改的值,因此无需执行另一个SELECT.

除此之外,我会说这取决于你的环境.如果应用程序是关键任务的,并且如果这些列没有正确维护将会失败,那么我会坚持使用触发器.

如果这只是为了方便前端(并且它可以优雅地处理因错误值而导致的冲突),那么JPA方法可能更容易维护.