开发者

Triggers vs. JPA @PrePersist for creation and update timestamps pros and cons

I am building a new web app and I am using Spring, JPA/Hibernate, and Postgres. Some of my tables have creation_ts and lastupdate_ts columns which are timestamp columns that track when an insert occurred and when the last update occurred on a row.

I am also using a naming convention for columns in my tables so as a matter of design policy every table is guaranteed to have two columns pkey which is an integer surrogate key, and version for optimistic locking.

I have two ways to keep these fields up to date.

Option A: use triggers

This is the solution I have in place right now, I have two Postgres trigger that fire on insert and update and will keep these fields up to date. and I have two classes.

@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;
    }
}

and I have

@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;
    }
}

Option B: Use JPA listeners

In this option I would use JPA listeners to keep to timestamp columns up-to-date.

My Question:

Which of those two approaches is better? As I see things here is my personal list of pros and cons of each option and I very interested from hearing the experience of others with these two choices.

Option A pros:

  1. Database is doing the updates with the triggers so there is no danger of having clock skew in the cluster running the web app.
  2. If a non-JPA application accesses the database the requirement to keep those two columns is enforced.

Option A cons:

  1. Have to do a select after the insert and update to read the values that the triggers put into place.
  2. I am using hibernate annotations to read back the values

Option B pros:

  1. Less typing when creating the DDL
  2. No need to read back values from the database after insert and update
  3. Pure JPA annotations no hibernate specific annotations

Option B cons:

  1. Danger of clock skew in the cluster
  2. Fields set whenever the JPA provider decides to call the callback methods not predictable

How you would solve this pr开发者_如何学Gooblem for a new app where you have total control over the database and the java code.


Have to do a select after the insert and update to read the values that the triggers put into place.

You can use INSERT ... RETURNING or UPDATE ... RETURNING to retrieve the values that were changed by the trigger, so there is no need to do another SELECT.

Apart from that, I'd say it depends on your environment. If the application is mission critical and will fail miserably if those columns aren't maintained correctly, then I'd stick with the triggers.

If this is only for convenience in the front end (and it can handle conflicts due to incorrect values gracefully), then the JPA approach is probably easier to maintain.


I'm currently using Option A (with all your frameworks and PostgreSQL as well) in the following manner:

@Column(insertable = false, updatable = false, nullable = false, columnDefinition = "timestamp without time zone default CURRENT_TIMESTAMP")
@Generated(GenerationTime.INSERT)
public Date getCreatedIn() {
    return createdIn;
}

If you use the columnDefinition as written in the code you won't have to select the object again neither write any code to set the date on your objects. I've never used the JPA callbacks other than to connect Envers framework but I can say it looks too much effort only to set the date on specific objects.


Danger of clock skew in the cluster

I'd say not to worry about it. It can fail in the cluster just like it could fail in the database. In a proper production environment, you'd have your own NTP servers, and your cluster would sync with that.

I usually prefer to keep everything in Java, as a centralized place for "logic" is desirable (for me). Placing logic in triggers is acceptable if you have non-Java applications consuming it.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜