在很多行业的软件设计中,数据安全都是非常重要的。很多时对数据的每一次修改操作都需要记录变更以备后期审计或者数据回滚。既然这个是通用功能需求,Hibernate Envers 提供了简单的通用实现,把每次数据表的变更都记录到对应配置的审计表中,实现数据变更的自动记录。
Hibernate Envers是如何做到数据变更自动记录到审计表的呢,这个其实非常简单,就是利用了Hibernate自己的事件监听机制。通过对Hibernate的操作事件监听记录修改数据的内容。
首先,先配置数据对象需要被监听的字段,这个可以通过简单的Annotation来实现。Envers常用的Annotation有:
1. 用于对象的:
@Audited 标记该实体类或属性支持数据修改记录。
@NotAudited 标记该属性不支持数据修改记录,典型如乐观锁version字段。
2. 用于记录全局修订版本,时间戳以及其它可能需要数据时的:
@RevisionEntity 实现为数据修改记录表保存其他自定义内容
@RevisionTimestamp 记录修改时间,必须配合@RevisionEntity使用
@RevisionNumber 修改记录表的版本id 通常是配置成主键。
接着配置hibernate envers监听数据变更(一般增,删,改,极少设计查询)
<bean id="sessionFactory" class="org.springframework.orm.hibernate4.LocalSessionFactoryBean ">
<property name="dataSource">
<ref local="dataSource" />
</property>
*<property name="eventListeners">
<map>
<entry key="post-insert" value-ref="enversEventListener" />
<entry key="post-update" value-ref="enversEventListener" />
<entry key="post-delete" value-ref="enversEventListener" />
<entry key="post-collection-recreate" value-ref="enversEventListener" />
<entry key="pre-collection-remove" value-ref="enversEventListener" />
<entry key="pre-collection-update" value-ref="enversEventListener" />
</map>
</property>*
*<bean name="enversEventListener" class="org.hibernate.envers.event.AuditEventListener" />*
最后在hibernate的配置文件中设置审计表的属性相关信息。
<property name="hibernateProperties">
<!-- 配置版本数据 -->
<props>
<!--配置审计表名的后缀,默认为空 -->
<prop key="org.hibernate.envers.audit_table_suffix"></prop>
<!--配置审计表名的前缀,默认为_AUD -->
<prop key="org.hibernate.envers.audit_table_prefix">_AUDIT</prop>
<!--配置审计表中记录版本号的字段名称 -->
<prop key="org.hibernate.envers.revision_field_name">REVISION_ID</prop>
<!--配置审计表中数据操作类型的字段名称,0:新增 1:修改 2:删除 -->
<prop key="org.hibernate.envers.revision_type_field_name">REVTYPE</prop>
<!--配置是否支持关联表修改时记录修改记录,默认为true -->
<prop key="org.hibernate.envers.revision_on_collection_change">true</prop>
<!--配置是否不对乐观锁字段修改时记录修改记录,即使用Version字段,默认值为true -->
<prop key="org.hibernate.envers.do_not_audit_optimistic_locking_field">true</prop>
<!--配置是否在删除操作时,记录所有字段还是只记录id值。默认为false false:只记录id true:记录全部字段 -->
<prop key="org.hibernate.envers.store_data_at_delete">true</prop>
</props>
</property>
这里有一个问题要注意就是Aduit table的生成,我个人不太喜欢hibernate的auto hbm2ddl,所以我都是自己手动生成对于的SQL ddl,如果需要auto ddl,那么需要配置hibernate.hbm2ddl.auto为 create, create-drop 或者 update。一般配置为update。
使用Envers存在的问题:
1. 随着业务操作的频繁,审计表数据增长过快
2. 有时候为了修复系统问题,部分数据操作可能会直接使用SQL,绕过Hibernate,需要注意这类数据变更的记录和处理
3. 数据表设计需包含创建用户和更新用户信息,以及创建时间和更新时间,否则变更信息记录不完全。
4. 中途系统升级对象需要添加新的持久属性的时候,需要处理数据表以及对应的审计表。
其它没有涉及的部分:
1. 限制:http://docs.jboss.org/envers/docs/#exceptions-wontbesupported
2. 额外数据信息记录实现:http://docs.jboss.org/envers/docs/#revisionlog
3. 变更数据查询:http://docs.jboss.org/envers/docs/#queries