Hibernate监听器Listener实现用户操作日志

网友投稿 371 2022-10-09

Hibernate监听器Listener实现用户操作日志

网上搜索发现,实现用户操作日志的方式有:自定义注解方式、Hibernate拦截器方式、Hibernate监听器方式等。

1、自定义注解方式较为麻烦,需要进行操作记录的方法均需要添加注解,但是相对的操作描述更为针对性,缺点是无法获得所操作的实体ID以及成员;

2、拦截器方式经我自己试验,拦截器是在Hibernate操作数据库之前执行的,所以同样获取不了所操作的实体ID和成员,但是相对注解方式来说,不用在原有代码上更改添加注解等,耦合性比较低。

使用拦截器需要保证数据库操作均是对实体类的操作,即使用save、update、delete、get、load等方式,原生sql语句的执行是不会被拦截的;

3、监听器方式是我最终采用的方法,监听器是在Hibernate操作数据库之后执行的回调方式,可以获取操作实体的ID和成员变量,同样的相对业务层耦合性低,

使用监听器需要保证数据库操作均是对实体类的操作,即使用save、update、delete、get、load等方式,原生sql语句的执行是不会被拦截的。

下边展示我的代码:

这部分是监听器的注册部分

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.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 /** * 监听修改事件 */ @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) 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"+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,实现功能效果就好,哈哈

版权声明:本文内容由网络用户投稿,版权归原作者所有,本站不拥有其著作权,亦不承担相应法律责任。如果您发现本站中有涉嫌抄袭或描述失实的内容,请联系我们jiasou666@gmail.com 处理,核实后本网站将在24小时内删除侵权内容。

上一篇:SpringBoot @Retryable注解
下一篇:Java由浅入深通关抽象类与接口上
相关文章

 发表评论

暂时没有评论,来抢沙发吧~