Entity 生命週期攔截器


先前看過的,Session Bean 與 Message-Driven Bean 有其生命週期與回呼方法:

Entity類似的,也可以設定生命週期回呼方法,在其儲存、載入、更新、移除等適當的時機被呼叫,你可以在對應的回呼方法中進行日誌、效能測試、資料驗證、通知改變等動作。

下表列出Entity相關的生命週期回呼方法標註:
@PrePersist EntityManager儲存Entity之前呼叫
@PostPersist EntityManager儲存Entity之後呼叫
@PostLoad EntityManager查詢Entity之後呼叫,像是查詢、find()、refresh()操作
@PreUpdate EntityManager將Entity與資料庫同步更新發生前呼叫
@PostUpdate EntityManager將Entity與資料庫同步更新發生後呼叫
@PreRemove EntityManager移除Entity前呼叫
@PostRemove EntityManager移除Entity後呼叫

這些生命週期回呼標註,可以直接標註在Entity上,例如:
@Entity
@Table(name="T_USER")
public class User implements Serializable {
    ...
    @PostPersist
    @PrePersist
    @PostLoad
    @PreUpdate
    @PostUpdate
    @PreRemove
    @PostRemove
    public void monitorUser() {
        System.out.println("your action....XD");
    }
}

不過建議可以設計一個傾聽器,將生命週期回呼方法定義其上,例如:
public class UserListener {
    @PostPersist
    @PrePersist
    @PostLoad
    @PreUpdate
    @PostUpdate
    @PreRemove
    @PostRemove
    public void monitor(Object o) {
        User user = (User) o;
        System.out.println(user.getName());
    }
}

傾聽器的回呼方法接受一個物件作為參數,回呼方法呼叫時會傳入Entity實例,然後定義Entity時,可以使用@EntityListeners來指定傾聽器:
@Entity
@EntityListeners(onlyfun.caterpillar.UserListener.class)
@Table(name="T_USER")
public class User implements Serializable {
    ...
}

@EntityListeners中可以定義多個傾聽器,例如:
@EntityListeners(onlyfun.caterpillar.UserListener.class, onlyfun.caterpillar.SomeListener.class, onlyfun.caterpillar.OtherListener.class)

傾聽器執行的順序為定義時的先後順序,若是在父子類別關係中,父類別的傾聽器會先執行,而後是子類別傾聽器。

若您想要所有Entity都套用一個預設傾聽器,可以定義在persistence.xml中,例如:
<persistence-unit name="sample">
    ...
    <default-entity-listeners>
        onlyfun.caterpillar.SomeListener.class
    </default-entity-listeners>
    ...
</persistence-unit>

在定義傾聽器時,您還可以使用@ExcludeDefaultListeners、@ExcludeSuperClassListeners來排除預設傾聽器或父類別傾聽器的執行,例如:
@Entity
@ExcludeDefaultListeners
@ExcludeSuperClassListeners
@EntityListeners(onlyfun.caterpillar.PowerUserListener.class)
public class PowerUser extends User {
    ....
}