利用Hibernate監聽器實現使用者動作記錄

來源:互聯網
上載者:User

標籤:

網上搜尋發現,實現使用者動作記錄的方式有:自訂註解方式、Hibernate攔截器方式、Hibernate監聽器方式等。

1、自訂註解方式較為麻煩,需要進行操作記錄的方法均需要添加註解,但是相對的操作描述更為針對性,缺點是無法獲得所操作的實體ID以及成員;

2、攔截器方式經我自己實驗,攔截器是在Hibernate操作資料庫之前執行的,所以同樣擷取不了所操作的實體ID和成員,但是相對註解方式來說,不用在原有代碼上更改添加註解等,耦合性比較低。

使用攔截器需要保證資料庫操作均是對實體類的操作,即使用save、update、delete、get、load等方式,原生sql語句的執行是不會被攔截的;

3、監聽器方式是我最終採用的方法,監聽器是在Hibernate操作資料庫之後執行的回調方式,可以擷取操作實體的ID和成員變數,同樣的相對業務層耦合性低,

使用監聽器需要保證資料庫操作均是對實體類的操作,即使用save、update、delete、get、load等方式,原生sql語句的執行是不會被攔截的。

 

下邊展示My Code:

這部分是監聽器的註冊部分

 1 import javax.annotation.PostConstruct; 2  3 import org.hibernate.SessionFactory; 4 import org.hibernate.event.service.spi.EventListenerRegistry; 5 import org.hibernate.event.spi.EventType; 6 import org.hibernate.internal.SessionFactoryImpl; 7 import org.springframework.beans.factory.annotation.Autowired; 8 import org.springframework.stereotype.Component; 9 10 /** 11  * hibernate的事件監聽註冊 12  * @author tianzhen13  */  14 @Component  15 public class HibernateEvent {  16   17     @Autowired18     private SessionFactory sessionFactory;  19     @Autowired  20     private OperListener operListener;  21       22     @PostConstruct 23     public void registerListeners() {  24         EventListenerRegistry registry = ((SessionFactoryImpl) sessionFactory).getServiceRegistry().getService(  25                 EventListenerRegistry.class);  26         registry.getEventListenerGroup(EventType.POST_COMMIT_INSERT).appendListener(operListener);//對實體儲存的監聽27         registry.getEventListenerGroup(EventType.POST_COMMIT_UPDATE).appendListener(operListener);//對實體修改的監聽28         registry.getEventListenerGroup(EventType.POST_COMMIT_DELETE).appendListener(operListener);//對實體刪除的監聽29     }  30 }

這部分是監聽器

import java.io.Serializable;import java.text.SimpleDateFormat;import java.util.Date;import javax.servlet.http.HttpSession;import org.hibernate.Session;import org.hibernate.event.spi.PostCommitDeleteEventListener;import org.hibernate.event.spi.PostCommitInsertEventListener;import org.hibernate.event.spi.PostCommitUpdateEventListener;import org.hibernate.event.spi.PostDeleteEvent;import org.hibernate.event.spi.PostInsertEvent;import org.hibernate.event.spi.PostUpdateEvent;import org.hibernate.persister.entity.EntityPersister;import org.hibernate.type.Type;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.stereotype.Component;import com.nuctech.model.Useroper;import com.nuctech.util.Constant;/**  * hibernate的事件監聽 * @author tianzhen */  @Componentpublic class OperListener implements PostCommitDeleteEventListener,PostCommitInsertEventListener,PostCommitUpdateEventListener{    private static final long serialVersionUID = -4253791237768268101L;        @Autowired    private HttpSession httpSession;    /**     * 監聽修改事件     */    @Override    public void onPostUpdate(PostUpdateEvent event) {        StringBuffer des = new StringBuffer();//操作描述        des.append("更新操作,更新內容{");        String diff = arrayDiff(event.getState(), event.getOldState(), event.getPersister().getPropertyNames(), event.getPersister().getPropertyTypes());//判斷修改了哪些部分,並拼接成字串        des.append(diff);        des.append("}");        saveOperLog(event.getSession(), event.getEntity().getClass().getSimpleName(), event.getId(), des);    }    /**     * 監聽插入事件     */    @Override    public void onPostInsert(PostInsertEvent event) {        if(!(event.getEntity() instanceof Useroper)){//當是對使用者動作表的插入時,不進行操作,否則進入死迴圈            StringBuffer des = new StringBuffer();//操作描述            des.append("建立操作,建立內容{");            String inser = arrayToString(event.getState(), event.getPersister().getPropertyNames(), event.getPersister().getPropertyTypes());//判斷添加的哪些成員,並拼接成字串            des.append(inser);            des.append("}");            saveOperLog(event.getSession(), event.getEntity().getClass().getSimpleName(), event.getId(), des);        }    }    /**     * 監聽刪除事件     */    @Override    public void onPostDelete(PostDeleteEvent event) {        StringBuffer des = new StringBuffer();//操作描述        des.append("刪除操作,刪除內容{");        String del = arrayToString(event.getDeletedState(), event.getPersister().getPropertyNames(), event.getPersister().getPropertyTypes());//判斷刪除了哪些成員,並進行拼接        des.append(del);        des.append("}");        saveOperLog(event.getSession(), event.getEntity().getClass().getSimpleName(), event.getId(), des);    }        /**     * 日誌的添加     * @param session     * @param des     */    private void saveOperLog(Session session, String tableName, Serializable targetId, StringBuffer des){        int currUserId = (int) httpSession.getAttribute(Constant.CURRENT_USERID);//擷取操作人        Date date = new Date();        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");        String time = sdf.format(date);//操作日期        String sql = "INSERT useroper(UserID,TableName,TargetID,OperDesc,OperTime) VALUES("+currUserId+",‘"+tableName+"‘,"+targetId+",‘"+des.toString()+"‘,‘"+time+"‘)";        Session logSession = session.getSessionFactory().openSession();//重新開啟一個新的Hibernate session,並在使用完進行關閉,不可使用原session。        logSession.createSQLQuery(sql).executeUpdate();        logSession.close();    }        /**     * 數組轉字串     * @param o 成員值     * @param names 成員名     * @param types 成員類型     * @return     */    private String arrayToString(Object[] o, String[] names, Type[] types){        StringBuffer result = new StringBuffer();        for(int i=0;i<o.length;i++){            if(types[i].isAssociationType())//外鍵忽略處理                continue;            result.append(names[i]+":"+o[i]+";");        }        if(result.toString().equals(""))            result.append(";");        return result.substring(0, result.length()-1);    }        /**     * 數組不同部分轉字串     * @param n 成員新值     * @param o 成員原值     * @param names 成員名     * @param types 成員類型     * @return     */    private String arrayDiff(Object[] n, Object[] o, String[] names, Type[] types){        StringBuffer result = new StringBuffer();        //各參數數組均按序傳進來的,按index取值即可        for(int i=0;i<n.length;i++){            if(types[i].isAssociationType())//外鍵忽略處理                continue;            //如不相等,則加入字串中            if(!String.valueOf(n[i]).equals(String.valueOf(o[i]))){                result.append(names[i]+":"+o[i]+">"+n[i]+";");            }        }        return result.substring(0, result.length()-1);    }    @Override    public boolean requiresPostCommitHanding(EntityPersister persister) {        return true;    }    @Override    public void onPostUpdateCommitFailed(PostUpdateEvent event) {            }    @Override    public void onPostInsertCommitFailed(PostInsertEvent event) {            }    @Override    public void onPostDeleteCommitFailed(PostDeleteEvent event) {            }}

我使用的監聽器介面均為PostCommitDeleteEventListener、PostCommitInsertEventListener、PostCommitUpdateEventListener,而不是PostDeleteEventListener、PostInsertEventListener、PostUpdateEventListener,前三者是商務邏輯對資料庫操作已經Commit後進行回調,後三者則不是,後三者在進行監聽時,雖然可以擷取各項值,但是在對值進行資料庫記錄時就會很麻煩,容易出現事物鎖等待逾時的Bug,導致業務處理也不能完成,本人菜鳥沒有找到解決辦法,用的是前三者的介面,anyway,實現功能效果就好,哈哈

利用Hibernate監聽器實現使用者動作記錄

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.