在Hibernate中,有兩種方式能夠捕獲實體對象的GRUD操做並執行相應的處理java
Hibernate回調(org.hibernate.classic.Lifecycle接口):sql
//Provides callbacks from the Session to the persistent object. //Persistent classes may implement this interface but they are not //required to. //If a CallbackException is thrown, the operation is vetoed and the //exception is passed back to the application. public interface Lifecycle { //If onSave(), onUpdate() or onDelete() return VETO, //the operation is silently vetoed. public static final boolean VETO = true; public static final boolean NO_VETO = false; //Called just before the object is saved public boolean onSave(Session s) throws CallbackException; //Called when an entity is passed to Session.update(). //This method is not called every time the object's //state is persisted during a flush. public boolean onUpdate(Session s) throws CallbackException; //Called just before an object is deleted public boolean onDelete(Session s) throws CallbackException; //Called just after an object is loaded public void onLoad(Session s, Serializable id); }
須要注意的地方:安全
1,若是onSave()、onUpdate()、onDelete()方法返回VOTE(true)或者在以上方法中拋出了CallbackException異常,操做將會中止而不會調用以後的Session.save()、Session.update()、Session.delete()方法session
2,並非每次調用Session.update()方法以前都會調用onUpdate()方法併發
3,調用Session.get()方法會直接返回實體對象,故在調用該方法後會當即調用onload()方法,而調用Session.load()方法返回的是實體對象的代理,故在調用該方法後不會當即調用onload()方法,對象在第一次使用時纔會真正加載,而在對象真正加載完成以後纔會調用onload()方法app
4,不能直接使用方法中的Session對象,該方法是由當前Session負責調用,若是在這些方法中又調用當前Session進行持久化,將致使Session內部狀態混亂ide
在onSave()方法中調用Session.save()方法將會致使死循環,可是在onSave()方法中執行Session.update()方法卻沒有報異常,不過一般方法只負責記錄日誌,數據合法性校驗等簡單工做,不會在這裏再次調用Session對象完成數據持久化,故不需考慮太多post
提到Lifecycle接口,一般也要提到Validatable接口(org.hibernate.classic.Validatable):ui
//Implemented by persistent classes with invariants that must //be checked before inserting into or updating the database. public interface Validatable { //Validate the state of the object before persisting it. //If a violation occurs, throw a ValidationFailure. //This method must not change the state of the object by //side-effect. public void validate() throws ValidationFailure; }
只有在對象插入和對象更新時纔會調用validate()方法對對象數據合法性進行校驗this
public class User implements Serializable,Lifecycle,Validatable{ private Integer id; private String name; private Integer age; private static final long serialVersionUID = 1L; public User(){} public Integer getId() { return id; } public void setId(Integer id) { this.id = id; } public String getName() { return name; } public void setName(String name) { this.name = name; } public Integer getAge() { return age; } public void setAge(Integer age) { this.age = age; } public boolean onSave(Session s) throws CallbackException { System.out.println("********on save********"); System.out.println("id :" + id); System.out.println("name :" + name); System.out.println("age :" + age); return Lifecycle.NO_VETO; } @Override public boolean onUpdate(Session s) throws CallbackException { System.out.println("********on update********"); System.out.println("id :" + id); System.out.println("name :" + name); System.out.println("age :" + age); return Lifecycle.VETO; } @Override public boolean onDelete(Session s) throws CallbackException { System.out.println("********on delete********"); throw new CallbackException("Delete operation is not allowed!"); } @Override public void onLoad(Session s, Serializable id) { System.out.println("********on load********"); System.out.println("id :" + id); } @Override public void validate() throws ValidationFailure { System.out.println("~~~~~~~~valid~~~~~~~~"); if(id < 0) throw new ValidationFailure("Illegal id!"); if(name == null || name.equals("")) throw new ValidationFailure("Illegal name!"); if(age < 0 || age > 150) throw new ValidationFailure("Illegal age!"); } }
因爲這種方式對POJO帶有侵入性,因此不建議使用
Hibernate攔截(org.hibernate.Interceptor接口):
接口定義了很是多的方法,基本上經過命名就能夠看出其功能,就不一一介紹了
不建議直接繼承Interceptor接口,更好的方式是繼承EmptyInterceptor類,並重寫須要的方法,EmptyInterceptor接口以下:
public class EmptyInterceptor implements Interceptor, Serializable { public static final Interceptor INSTANCE = new EmptyInterceptor(); protected EmptyInterceptor() {} public void onDelete( Object entity, Serializable id, Object[] state, String[] propertyNames, Type[] types) {} public boolean onFlushDirty( Object entity, Serializable id, Object[] currentState, Object[] previousState, String[] propertyNames, Type[] types) { return false; } public boolean onLoad( Object entity, Serializable id, Object[] state, String[] propertyNames, Type[] types) { return false; } public boolean onSave( Object entity, Serializable id, Object[] state, String[] propertyNames, Type[] types) { return false; } public void postFlush(Iterator entities) {} public void preFlush(Iterator entities) {} public Boolean isTransient(Object entity) { return null; } public Object instantiate(String entityName, EntityMode entityMode, Serializable id) { return null; } public int[] findDirty(Object entity, Serializable id, Object[] currentState, Object[] previousState, String[] propertyNames, Type[] types) { return null; } public String getEntityName(Object object) { return null; } public Object getEntity(String entityName, Serializable id) { return null; } public void afterTransactionBegin(Transaction tx) {} public void afterTransactionCompletion(Transaction tx) {} public void beforeTransactionCompletion(Transaction tx) {} public String onPrepareStatement(String sql) { return sql; } public void onCollectionRemove(Object collection, Serializable key) throws CallbackException {} public void onCollectionRecreate(Object collection, Serializable key) throws CallbackException {} public void onCollectionUpdate(Object collection, Serializable key) throws CallbackException {} }
示例以下:
public class LogInterceptor extends EmptyInterceptor { private static final long serialVersionUID = 1L; @Override public boolean onLoad(Object entity, Serializable id, Object[] state, String[] propertyNames, Type[] types) { System.out.println(entity.getClass().getName() + " loaded."); return false; } }
值得注意的是能夠配置2種範圍的攔截器
SessionFactory範圍的攔截器:
因爲多個Session可能併發的使用SessionFactoruy範圍的攔截器,故該攔截器必須是線程安全的
LogInterceptor li = new LogInterceptor(); Configuration conf = new Configuration().setInterceptor(li); SessionFactory sessionFactory = conf.configure().buildSessionFactory(); Session sess = sessionFactory.openSession();
Session範圍的攔截器:
LogInterceptor li = new LogInterceptor(); Configuration conf = new Configuration(); SessionFactory sessionFactory = conf.configure().buildSessionFactory(); Session sess = sessionFactory.openSession(li);