- 浏览: 162515 次
- 性别:
- 来自: 杭州
文章分类
最新评论
-
mengyue0477:
最后还不忘吐槽一下 哈哈 太逗了
spring容器的懒加载lazy-init设置 -
comet0515:
不是maven工程能不能用checkstyle插件?job是一 ...
jenkins 配置checkstyle -
xfxlch:
http://docs.spring.io/spring-bo ...
NoteBook -
With_Me_Forever:
太浅了。我最近也在看着方面的资料,一起进步把。
互联网金融定义 -
xfxlch:
在http://r.m.baidu.com/6pmxgig
NoteBook
需求:
对所有操作数据库的事件,添加audit log, 此log持久化到一张单独的audit_log表,以供操作人员可以查阅跟踪。
方案:
Hibernate Interceptor 提供了一个拦截器,使用切面的方法,拦截所有对DB的操作,like:persist, merge, remove event。
实现:
首先是创建一个AuditlogInterceptor,来实现对数据库操作的拦截。 这个Interceptor要继承Hibernate的EmptyInterceptor, 然后我们同时重写onsave,ondelete,onFlushDirty, postFlush等方法来实现我们自己的需求:
其次把这个拦截器配置到我们的事务里去。
配置文件:比如数据源配置文件:datasource-context.xml:
添加:
由于这里是我自己去创建了一个PersistenceUnit,所以Hibernate会要求有一个persistence.xml文件,在META-INFO 文件夹下面,我们只要创建这个文件,并不需要指定,Hibernate会自动到该目录下去查找这个文件,文件名不能写错:
最后就是要去创建Entity来保持audit log, 比如AuditEntity.java
--EOF--
对所有操作数据库的事件,添加audit log, 此log持久化到一张单独的audit_log表,以供操作人员可以查阅跟踪。
方案:
Hibernate Interceptor 提供了一个拦截器,使用切面的方法,拦截所有对DB的操作,like:persist, merge, remove event。
实现:
首先是创建一个AuditlogInterceptor,来实现对数据库操作的拦截。 这个Interceptor要继承Hibernate的EmptyInterceptor, 然后我们同时重写onsave,ondelete,onFlushDirty, postFlush等方法来实现我们自己的需求:
public class AuditLogInterceptor extends EmptyInterceptor { /** * serialVersionUID */ private static final long serialVersionUID = -4829761117655964386L; private static final Logger logger = LoggerFactory.getLogger(AuditLogInterceptor.class); private static final String EMPTY_STRING = ""; private static final String DELETE = "postFlush - delete"; private static final String INSERT = "postFlush - insert"; private static final String UPDATE = "postFlush - update"; private static EntityManager entityManager = null; static { entityManager = Persistence.createEntityManagerFactory("auditLog").createEntityManager(); } //FIXME thread local private Set<IAuditable> inserts = new HashSet<IAuditable>(); private Set<IAuditable> updates = new HashSet<IAuditable>(); private Set<IAuditable> deletes = new HashSet<IAuditable>(); @Override public synchronized boolean onSave(Object entity, Serializable id, Object[] state, String[] propertyNames, Type[] types) throws CallbackException { logger.info("onSave"); if (entity instanceof IAuditable) { inserts.add((IAuditable)entity); } return false; } @Override public synchronized boolean onFlushDirty(Object entity, Serializable id, Object[] currentState, Object[] previousState, String[] propertyNames, Type[] types) throws CallbackException { logger.info("onFlushDirty"); if (entity instanceof IAuditable) { updates.add((IAuditable)entity); } return false; } @Override public synchronized void onDelete(Object entity, Serializable id, Object[] state, String[] propertyNames, Type[] types) { logger.info("onDelete"); if (entity instanceof IAuditable) { deletes.add((IAuditable)entity); } } /** * called before commit into database */ @SuppressWarnings("rawtypes") @Override public void preFlush(Iterator iterator) { logger.info("preFlush"); } /** * called after committed into database */ @SuppressWarnings("rawtypes") @Override public synchronized void postFlush(Iterator iterator) { logger.info("postFlush"); String username = SecurityContextHolder.getContext().getAuthentication().getName(); Collection collection = SecurityContextHolder.getContext() .getAuthentication() .getAuthorities(); String role = collection.toString(); if (inserts.isEmpty() && updates.isEmpty() && deletes.isEmpty()) { return; } try { if (!entityManager.getTransaction().isActive()) { entityManager.getTransaction().begin(); } for (IAuditable entity : inserts) { persistenceEntity(entity, entityManager, username, role, INSERT, null); } for (IAuditable entity : updates) { IAuditable preStateEntity = null; preStateEntity = entityManager.find(entity.getClass(), entity.getId()); List<String> valueList = getNewOldValues(entity, preStateEntity); String oldValues = valueList.get(0); String changeValues = valueList.get(1); if (!oldValues.equals(changeValues)) { persistenceEntity(entity, entityManager, username, role, UPDATE, valueList); } } for (IAuditable entity : deletes) { persistenceEntity(entity, entityManager, username, role, DELETE, null); } } catch (Exception e) { e.printStackTrace(); } finally { updates.clear(); inserts.clear(); deletes.clear(); if (entityManager.isOpen() && entityManager.getTransaction().isActive()) { logger.info("finally cause"); entityManager.getTransaction().commit(); } } } private void persistenceEntity(IAuditable entity, EntityManager em, String username, String role, String comments, List<String> changeValueslist) { logger.info(comments); AuditLogEntity logEntity = new AuditLogEntity(); logEntity.setComments(comments); logEntity.setOperator(StringUtils.isEmpty(username) ? "default" : username); logEntity.setRole(StringUtils.isEmpty(role) ? "default" : role); logEntity.setCreatedOn(new Date()); //sql date? logEntity.setUpdatedOn(new Date()); if (changeValueslist == null && DELETE.equals(comments)) { logEntity.setNewvalue(EMPTY_STRING); logEntity.setOldvalue(entity.getLogDeatil()); } else if (changeValueslist == null && INSERT.equals(comments)) { logEntity.setNewvalue(entity.getLogDeatil()); logEntity.setOldvalue(EMPTY_STRING); } else if (UPDATE.equals(comments)) { String newvalue = changeValueslist.get(1); String oldvalue = changeValueslist.get(0); logEntity.setNewvalue(newvalue); logEntity.setOldvalue(oldvalue); } logEntity.setEntity(entity.getClass().getName()); em.persist(logEntity); } }
其次把这个拦截器配置到我们的事务里去。
配置文件:比如数据源配置文件:datasource-context.xml:
添加:
<bean id="entityManagerFactory" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean"> <property name="persistenceUnitName" value="auditLog" /> <property name="dataSource" ref="dataSource" /> <property name="packagesToScan" value="com.statestreet.fcm.cfd" /> <property name="jpaVendorAdapter"> <bean class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter" /> </property> <!-- new added <property name="persistenceXmlLocation" value="classpath:persistence.xml" /> --> <property name="jpaProperties"> <props> <prop key="hibernate.dialect">org.hibernate.dialect.OracleDialect</prop> <prop key="hibernate.show_sql">true</prop> <prop key="hibernate.cache.use_second_level_cache">false</prop> <prop key="hibernate.cache.use_query_cache">false</prop> <prop key="hibernate.use_sql_comments">false</prop> <prop key="hibernate.format_sql">true</prop> <prop key="hibernate.temp.use_jdbc_metadata_defaults">false</prop> <!-- by clu --> <prop key="hibernate.ejb.interceptor">com.statestreet.fcm.cfd.interceptor.AuditLogInterceptor</prop> </props> </property> </bean>
由于这里是我自己去创建了一个PersistenceUnit,所以Hibernate会要求有一个persistence.xml文件,在META-INFO 文件夹下面,我们只要创建这个文件,并不需要指定,Hibernate会自动到该目录下去查找这个文件,文件名不能写错:
<?xml version="1.0" encoding="UTF-8"?> <persistence version="2.0" xmlns="http://java.sun.com/xml/ns/persistence" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/persistence http://java.sun.com/xml/ns/persistence/persistence_2_0.xsd"> <persistence-unit name="auditLog" transaction-type="RESOURCE_LOCAL"> <provider>org.hibernate.ejb.HibernatePersistence</provider> <properties> <property name="hibernate.archive.autodetection" value="class"/> <property name="hibernate.show_sql" value="true"/> <property name="hibernate.connection.driver_class" value="oracle.jdbc.OracleDriver"/> <property name="hibernate.connection.url" value="jdbc:oracle:thin:@"/> <property name="hibernate.connection.password" value="123"/> <property name="hibernate.connection.username" value="123"/> <property name="hibernate.dialect" value="org.hibernate.dialect.OracleDialect"/> <property name="hibernate.c3p0.min_size" value="5"/> <property name="hibernate.c3p0.max_size" value="20"/> <property name="hibernate.c3p0.timeout" value="300"/> <property name="hibernate.c3p0.max_statements" value="50"/> <property name="hibernate.c3p0.idle_test_period" value="3000"/> </properties> </persistence-unit> </persistence>
最后就是要去创建Entity来保持audit log, 比如AuditEntity.java
@Entity @Table(name = "AUDIT_LOG_DETAIL") public class AuditLogEntity implements Serializable { /** * serialVersionUID */ private static final long serialVersionUID = -1275702854046959229L; @Id @GeneratedValue private Long id; @Column(nullable = false ) private String operator; @Column(nullable = false ) private String role; @Column private String entity; @Column private String oldvalue; @Column private String newvalue; @Column private String comments; @Column(nullable = false) private Date createdOn; @Column(nullable = false) private Date updatedOn; }
--EOF--
发表评论
-
eclipse project .setting
2016-08-24 11:30 565有一个文件在.setting的目录下面: 文件名:org.ec ... -
jar命令工具
2016-01-23 20:29 611背景: 今天介绍两个jar的命令工具,对我个人来说,还是比较好 ... -
Java的按值传递
2016-01-23 19:30 508问题: 最近在看Mar ... -
Mac OS 安装java 开发环境
2016-01-03 13:00 1736我的机器是: 1. jdk1.7下载安装 jdk7:h ... -
记一次Java Rest Service Hang住的经历
2015-12-28 20:08 2651背景: 在前后端分开开发的过程中,前段的页面要调用后台Java ... -
一个String字符串的问题2
2015-12-14 14:22 564背景: 今天遇到个问题: String str = & ... -
我读重构这本书
2015-12-01 22:30 0第一点:关注变量命名。好的变量名能让读者更快更好的理解程序到底 ... -
系统log的编写
2015-11-16 09:41 0log很关键,一定要记录好对追踪问题有帮助的日志。 -
CAS 授权问题
2015-11-16 09:40 0CAS 授权问题 -
Caused by: java.lang.UnsupportedOperationException 解决方案
2015-10-21 22:09 4000背景: 今天在跑一个UnitTest,跑的过程中想在list ... -
LogBack 框架里log-access的使用
2015-10-18 16:05 7006背景: 想通过配置log-access来实现直接使用浏览器来访 ... -
how to fix "org.hamcrest.CoreMatchers.containsString cannot be resolved"
2015-09-23 23:12 2976背景: 山姆大叔比较喜欢用一些新的技术和新的特性,最近在jun ... -
java 打印金字塔
2015-08-24 00:53 734背景: 一个同事,面试应聘者喜欢用学校里学过的一个书本或者课后 ... -
纯jsp servlet 实现 upload file功能
2015-08-17 20:35 684本篇主要是简单的实现jsp servlet 的上传文件的功能, ... -
dos 命令窗口執行java 命令,帶包路徑
2015-07-26 12:16 508記錄一下,是為了自己下次再run java命令的時候,可以很快 ... -
tomcat 远程调试
2015-07-23 18:41 448背景: 我们在项目开发过程中,很多时候会遇到这样的情况:项目在 ... -
使用android studio 来开发hello world app的时候,遇到的一些坑。
2015-07-13 01:38 2093使用android studio 来开发h ... -
ThreadLocal
2015-05-11 07:22 372Java线程:深入ThreadLocal ThreadLo ... -
eclipse 加入tomcat 包
2015-03-24 01:09 397... -
Transforming XML with XSLT
2014-10-11 19:14 492public static void catalog() ...
相关推荐
使用拦截器时按如下步骤进行: (1)定义实现Interceptor接口的拦截器类 (2)通过Session启用拦截器,或者通过Configuration启用全局拦截器请看示例代码
拦截器 interceptor 过滤器 filter web.xml implements filter filterchain arg2.doFilter(req,resp); 监听器 servlet application /session /request 6/8 个 1、拦截器 定义拦截器的包 定义拦截器的...
使用Hibernate拦截器检测Persistence Context中的实体更改 使用Hibernate拦截器对数据库中的实体更改做出React 使用观察者设计模式来监视实体持久性更改并对其做出React 使用命令设计模式提供一种通用方法,可将...
支持Struts2 不支持Hibernate
9.2 利用拦截器(Interceptor)生成审计日志 9.3 Hibernate的事件处理机制 9.4 批量处理数据 9.4.1 通过Session来进行批量操作 9.4.2 通过StatelessSession来进行批量操作 9.4.3 通过HQL来进行批量操作 ...
-- 下面定义BeanNameAutoProxyCreator所需的事务拦截器--> <value>transactionInterceptor <!-- 此处可增加其他新的Interceptor --> <!--定义DAO Bean ,由于BeanNameAutoProxyCreator自动...
还有登录拦截器:com.light.framework.interceptor 字符集过滤器:com.light.framework.filter 项目字符集请用UTF-8 com.light.framework包中还有些小东西 自己看看吧 我是用MyEclipse6.0开发的(MyEclipse...
4.4.1 声明独立的拦截器和拦截器栈 74 4.4.2 将拦截器映射到动作组件 76 4.4.3 设置、覆盖拦截器参数 77 4.5 构建自定义拦截器 78 4.5.1 实现Interceptor接口 78 4.5.2 构建AuthenticationInterceptor拦截器 79 4.6 ...
9.2 利用拦截器(Interceptor)生成审计日志 9.3 Hibernate的事件处理机制 9.4 批量处理数据 9.4.1 通过Session来进行批量操作 9.4.2 通过StatelessSession来进行批量操作 9.4.3 通过HQL来进行批量操作 ...
9.2 利用拦截器(Interceptor)生成审计日志 9.3 Hibernate的事件处理机制 9.4 批量处理数据 9.4.1 通过Session来进行批量操作 9.4.2 通过StatelessSession来进行批量操作 9.4.3 通过HQL来进行批量操作 ...
9.2 利用拦截器(Interceptor)生成审计日志 9.3 Hibernate的事件处理机制 9.4 批量处理数据 9.4.1 通过Session来进行批量操作 9.4.2 通过StatelessSession来进行批量操作 9.4.3 通过HQL来进行批量操作 ...
18.3 使用DataSourceInjectorInterceptor拦截器 269 18.4 小结 273 第19章定制结果类型 274 19.1 概述 274 19.2 编写一个自定义的结果类型 274 19.3 使用新的结果类型 277 19.4 小结 279 第20章 Velocity 280...
filter:Log4jFormatFilter(格式化log4j日志输出的),SessionCheckFilter(登陆拦截器) interceptor:权限拦截包 listener:目前只有session的监听器,用于监听session的 service:具体的业务处理包 util:项目工具包 ...
-- 定义拦截器 --> class="org.springframework.transaction.interceptor.TransactionInterceptor"> <property name="transactionManager" ref="transactionManager"></property> ...
开发工具IntelliJ IDEA15,maven构建工程,使用spring4.1.1,demo集成jackson传输json,hibernate-validator校验数据,mybatis数据库持久框架,拦截器interceptor,aop构建事务等,让你快速入门spring
118 8.3.5 Struts2配置文件 119 8.4 Action的配置方式 121 8.4.1 动态方法调用 121 8.4.2 设置action元素的method属性 122 8.4.3 使用通配符配置action 122 8.4.4 默认action 123 8.5 拦截器Interceptor 123 8.5.1 ...
18.3 使用DataSourceInjectorInterceptor拦截器 269 18.4 小结 273 第19章 定制结果类型 274 19.1 概述 274 19.2 编写一个自定义的结果类型 274 19.3 使用新的结果类型 277 19.4 小结 279 第20章 Velocity 280 ...