14

I'm playing around a bit with JPA(Eclipselink to be specific). The below entity have a timestamp that's supposed to reflect whenever that entity was last updated.

What are the strategies for making JPA update that timestamp automatically every time this entity is changed ?

How would I go about if I also want a 'creation' timestamp, only set when the entity is first persisted, never allowed to be changed again ?

 @Entity
 public class Item implements Serializable {
     private static final long serialVersionUID = 1L;
     private Integer id;
     private String note;


    public Item () {
    }


    @Id
    @GeneratedValue(strategy=SEQUENCE)
    @Column(unique=true, nullable=false)
    public Integer getId() {
        return this.id;
    }

    public void setId(Integer id) {
        this.id = id;
    }


    @Column(length=255)
    @Column(nullable=false)
    public String getNote() {
        return this.note;
    }

    public void setNote(String note) {
        this.note = note;
    }

    @Column(nullable=false)
    public Timestamp getUpdated() {
        return this.updated;
    }

    public void setUpdated(Timestamp updated) {
        this.updated = updated;
    }


}
nos
  • 223,662
  • 58
  • 417
  • 506

4 Answers4

19

Use @PrePersist and @PreUpdate annotations and write your own event listener.

Take a look at this answer for details. It's tagged as Hibernate but is applicable to any JPA provider.

Community
  • 1
  • 1
ChssPly76
  • 99,456
  • 24
  • 206
  • 195
2

if you are using mysql, I think you can do the following to disable the timestamps from being updated from entity

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

for oracle you time have to set the timestamps from the entity using @PreUpdate annotation as explained above.

surajz
  • 3,471
  • 3
  • 32
  • 38
  • This is wrong for many reasons: (1) the above assumes that you're manually updating the timestamp thus setting "updatable" is pointless; (2) consequently, the above will not work without @PreUpdate / @PrePersist event listeners; (3) if you want database to generate your timestamps (which you seem to imply), you have to mark your properties as generated which is **not** in JPA standard; (4) finally, MySQL will not let you have 2 auto-updated timestamps in the same table. – ChssPly76 Nov 17 '09 at 01:05
  • Regarding mysql, you can create one or more triggers to update any number of columns such as a timestamp - you are not limited to 1 auto updated timestamp in a table. – nos Nov 17 '09 at 16:56
  • in MySql you can also create table with 2 timestamps and insert NULL on both field when inserting a record. create table ts ( last_updated_ts TIMESTAMP, created_ts TIMESTAMP, name varchar(5) ); insert into ts(last_updated_ts, created_ts, name) value (null, null, 'test'); Definitely trigger or annotation is better depending on how the client accesses the database. – surajz Nov 17 '09 at 17:19
1

Actually, surajz answer works. Consider a scenario where you are tracking 2 timestamps. You want to manually update them via the entity. You'd need to set one to updateble=false (the one you do not want updated when the record is updated), and leave the other free for updates.

That's what worked for me.

Marko
  • 20,385
  • 13
  • 48
  • 64
Jubz
  • 157
  • 2
  • 11
1

In Entity class

@Column
@UpdateTimestamp
private Timestamp updatedOn

@Column
@CreationTimestamp
private Timestamp createdOn

it will update automatically when any change in entity

Supported attribute types

java.time.LocalDate (since Hibernate 5.2.3)
java.time.LocalDateTime (since Hibernate 5.2.3)
java.util.Date
java.util.Calendar
java.sql.Date
java.sql.Time
java.sql.Timestamp

Example :

@Entity
public class MyEntity {
 
    @Id
    @GeneratedValue
    private Long id;
 
    @CreationTimestamp
    private Timestamp createdOn;
 
    @UpdateTimestamp
    private Timestamp updatedOn;
 
}
Khalid Habib
  • 1,100
  • 1
  • 16
  • 25