5.1 Oras ng pagbabago ng data

Kapag nag-imbak ka ng iba't ibang mga tala sa isang database sa loob ng maraming taon, dalawang tanong ang madalas na lumabas:

  • Kailan idinagdag ang entry na ito sa database?
  • Kailan huling binago ang entry na ito?

Ito ang mga madalas na gawain na ang dalawang column ay idinaragdag sa halos bawat talahanayan sa database:

  • nilikha_oras
  • updated_time

Ang una ay nag-iimbak ng petsa at oras na ginawa ang tala, at ang pangalawa ay nag-iimbak ng petsa at oras kung kailan ito huling binago. At ang bawat klase ng Entity ay may mga field:


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

Maaaring gawin ng hibernate ang lahat ng gawain ng pagkontrol kapag ang mga bagay sa database ay na-update na may dalawang anotasyon @CreationTimestampat @UpdateTimestamp.

Halimbawa:

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

Ang mga column na minarkahan ng mga anotasyong ito ay palaging mag-iimbak ng tamang oras kung kailan ginawa ang bagay at kung kailan ito huling binago.

5.2 @PrePersist annotation

Kung kailangan mo ng ilang mas kumplikadong script para makontrol ang oras ng isang bagay, ang Hibernate ay may mga anotasyon din para sa kasong ito. Maaari nilang markahan ang mga pamamaraan ng klase, at tatawagin ng Hibernate ang mga pamamaraang ito kapag nai-save nito ang bagay sa database. Mayroong 7 ganoong anotasyon sa kabuuan:

@PrePersist Tinatawag bago ang bagay ay nai-save sa database. (SQL INSERT)
@PostPersist Tinatawag kaagad pagkatapos mai-save ang bagay sa database. (SQL INSERT)
@PreRemove Tinawag bago tanggalin ang isang bagay sa database.
@PostRemove Tinatawag pagkatapos matanggal ang isang bagay mula sa database.
@PreUpdate Tinawag bago i-update (SQL UPDATE) ang isang bagay sa database.
@PostUpdate Tinatawag pagkatapos ng pag-update (SQL UPDATE) ng isang bagay sa database.
@postload Tinatawag pagkatapos ma-load ang bagay mula sa database.

Sumulat tayo ng isang halimbawa kung saan sasabihin natin sa isang klase ang tamang oras upang gawin at i-update ang mga bagay nito:

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

Kung ise-save ng Hibernate ang bagay sa unang pagkakataon, tatawagin nito ang paraan na may annotate na @PrePersist. Kung mag-a-update ito ng isang umiiral na bagay sa database, tatawagin nito ang pamamaraang may markang annotation @PreUpdate.

5.3 Pagdaragdag ng aming EntityListeners

Kung talagang kailangan mo, pagkatapos ay maaari mong paghiwalayin ang mga pamamaraan na tinatawag ng Hibernate mula sa bagay kung saan ito tumatawag sa kanila. Ang pagtutukoy ng JPA ay nagbibigay-daan sa iyo na magdeklara ng mga klase ng tagapakinig na tatawagin sa ilang partikular na oras kapag nagpoproseso ng mga object ng Entity.

Kung marami kang katulad na object ng Entity, maaari mong ilipat ang ilan sa mga ito sa base class at magdagdag ng Listener na kumokontrol sa kanilang pag-uugali. Halimbawa:


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


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

Pagkatapos para sa klase ng BaseEntity, maaari kang lumikha ng isang espesyal na klase ng tagapakinig:


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

At maaari mong ikonekta ang klase ng User at ang tagapakinig nito gamit ang ilang mga anotasyon:


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