在很多行業的軟件設計中,數據安全都是非常重要的。很多時對數據的每一次修改操作都需要記錄變更以備後期審計或者數據回滾。既然這個是通用功能需求,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