Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Triggers versus JPA Event

I'm doing a Web application using Spring 3.1.0.RELEASE, JSF 2.x, JPA 2 with Hibernate Provider, MySql 5.1.x. The application runs on Tomcat 7.X.

In my entities I have some date like last update date:

@Column(name = "last_update_date", insertable = false, updatable = false)
@Temporal(TemporalType.TIMESTAMP)
private Date lastUpdateDate;

For the moment I have a trigger that updates:

CREATE TRIGGER upd_site BEFORE UPDATE ON site
FOR EACH ROW SET NEW.last_update_date = CURRENT_TIMESTAMP();

It works fine, but I just notice that there is some callbacks methods in JPA http://www.objectdb.com/java/jpa/persistence/event

What is the best between JPA Events and the MySql's triggers ?

Thanks.

like image 771
La Chamelle Avatar asked Jun 21 '12 10:06

La Chamelle


People also ask

Is JPA the same as Spring data JPA?

Spring data jpa- it is same like jpa means we can describe in below way. Spring Data Jpa is jpa data abstraction access which means it likes a jpa but it add some extra functionality, Without jpa we can not implement the spring data jpa.

What is the difference between JPA and JPA data?

As we saw above, JPA is a standard for defining the persistence layer and Spring Data JPA is a sub-project under the Spring Framework umbrella which allows Spring applications to integrate with JPA.

Is Spring data JPA better than hibernate?

Conclusion. Hibernate is a JPA provider and ORM that maps Java objects to relational database tables. Spring Data JPA is an abstraction that makes working with the JPA provider less verbose. Using Spring Data JPA you can eliminate a lot of the boilerplate code involved in managing a JPA provider like Hibernate.


2 Answers

There is no best thing. A database trigger will update the last update date at every update of a row, whatever the way used to update the row (Hibernate, a JDBC query, or an update from your database admin tool). A JPA callback will only be invoked when the row is updated using JPA. You might want one or the other.

Another difference is that JPA is unaware of the trigger executed by the database. So if you update some field in your entity, and JPA flushed the change, the update date will be modified by the trigger, but the JPA entity will keep the old value of the update date in memory. So if this update date is displayed in the GUI after the update, the update date will be incorrect. You'll have to refresh the entity to get the latest update date.

like image 157
JB Nizet Avatar answered Sep 28 '22 07:09

JB Nizet


I have used it both ways with Triggers in the DB and with JPA listeners, I have settled on the JPA listeners because:

  • the only code talking to the database in JPA code so I don't have to worry about the time stamp fields falling out of date. (If this changes in the future I can add triggers and change my mapped super calss)

  • JPA listeners are less complex in the sense that I did not have to go creating lots of triggers in my database so I had less things to maintain. Since I am actively developing and changing the db structure as I go along its great not to have to go and update triggers as I rapidly iterate through the development.

  • I have complete control over the database and made a rule for the db that every table was going to have a integer pkey, and an integer version, and that the time stamped tables would have insert_ts and update_ts columns these are universal rules in my db design so life is easy I have these two mapped superclases that make all my enitites simple to code since I extend from them.

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

    @Override
    public String toString() {
        return "Presistable Object: pkey=" + this.pkey + " Object: " + this.getClass().getName();
    }
}

and

@MappedSuperclass
public class TimeStampedPersistableObject extends PersistableObject {

    @Column(name = "insert_ts")
    @Temporal(TemporalType.TIMESTAMP)
    private Date    insertTimestamp;

    @Column(name = "update_ts")
    @Temporal(TemporalType.TIMESTAMP)
    private Date    updateTimestamp;

    @SuppressWarnings("unused")
    @PrePersist
    private void onInsert() {
        this.insertTimestamp = new Date();
        this.updateTimestamp = this.insertTimestamp;
    }

    @SuppressWarnings("unused")
    @PreUpdate
    private void onUpdate() {
        this.updateTimestamp = new Date();
    }


    public Date getInsertTimestamp() {
        return this.insertTimestamp;
    }


    public Date getUpdateTimestamp() {
        return this.updateTimestamp;
    }
}
like image 30
ams Avatar answered Sep 28 '22 09:09

ams