5.1 Time of data change

When you store various records in a database for many years, two questions often arise:

  • When was this entry added to the database?
  • When was this entry last changed?

These are such frequent tasks that two columns are added to almost every table in the database:

  • created_time
  • updated_time

The first stores the date and time the record was created, and the second stores the date and time it was last modified. And each Entity class has fields:


@Entity
@Table(name = "entities")	
public class Entity {
  ...
 
  @Column(name="created_time")
  private Date created;
 
  @Column(name="updated_time")
  private Date updated;
}

Hibernate can do all the work of controlling when objects in the database are updated with two annotations @CreationTimestampand @UpdateTimestamp.

Example:

@Entity
@Table(name = "entities")
public class Entity {
  ...

	@CreationTimestamp
    @Temporal(TemporalType.TIMESTAMP)
    @Column(name = "create_date")
    private Date createDate;

	@UpdateTimestamp
    @Temporal(TemporalType.TIMESTAMP)
    @Column(name = "modify_date")
	private Date modifyDate;
}

The columns marked with these annotations will always store the correct time when the object was created and when it was last modified.

5.2 @PrePersist annotation

If you need some more complex scripts to control the time of an object, then Hibernate has annotations for this case too. They can mark class methods, and Hibernate will call these methods when it saves the object to the database. There are 7 such annotations in total:

@PrePersist Called before the object is saved to the database. (SQL INSERT)
@PostPersist Called immediately after the object is saved to the database. (SQL INSERT)
@PreRemove Called before deleting an object in the database.
@PostRemove Called after an object has been deleted from the database.
@PreUpdate Called before updating (SQL UPDATE) an object in the database.
@PostUpdate Called after an update (SQL UPDATE) of an object in the database.
@postload Called after the object has been loaded from the database.

Let's write an example where we tell a class the correct time to create and update its objects:

@Entity
@Table(name = "entities")
public class Entity {
  ...

  @Column(name="created_time")
  private Date created;

  @Column(name="updated_time")
  private Date updated;

  @PrePersist
  protected void onCreate() {
    created = new Date();
  }

  @PreUpdate
  protected void onUpdate() {
  updated = new Date();
  }
}

If Hibernate saves the object for the first time, then it will call the method annotated with @PrePersist. If it updates an existing object in the database, it will call the method marked with the annotation @PreUpdate.

5.3 Adding our EntityListeners

If you really need to, then you can separate the methods that Hibernate calls from the object on which it calls them. The JPA specification allows you to declare listener classes that will be called at certain times when processing Entity objects.

If you have a lot of similar Entity objects, then you can move some of them into the base class and add a Listener that would control their behavior. Example:


@MappedSuperclass
public abstract class BaseEntity {
 
    private Timestamp createdOn;
 
    private Timestamp updatedOn;
 
}


@Entity
public class User extends BaseEntity {
 
     @Id
     private Long id;
 
     private String name;
}

Then for the BaseEntity class, you can create a special listener class:


public class TimeEntityListener {
 
    public void onPersist(Object entity) {
    	if (entity instanceof BaseEntity) {
        	BaseEntity baseEntity = (BaseEntity) entity;
        	baseEntity.createdOn = now();
    	}
    }
 
    public void onUpdate(Object entity) {
    	if (entity instanceof BaseEntity) {
        	BaseEntity baseEntity = (BaseEntity) entity;
        	baseEntity.updatedOn = now();
    	}
    }
 
    private Timestamp now() {
    	return Timestamp.from(LocalDateTime.now().toInstant(ZoneOffset.UTC)   );
    }
}

And you can connect the User class and its listener using a couple of annotations:


@Entity
@EntityListeners(class= TimeEntityListener.class)
public class User extends BaseEntity {
 
     @Id
     private Long id;
 
     private String name;
}

undefined
1
Task
Module 4. Working with databases, level 12, lesson 4
Locked
Data creation and modification time
task1204