在 Spring Hibernate java 项目中使用“Envers”审计表
Posted
技术标签:
【中文标题】在 Spring Hibernate java 项目中使用“Envers”审计表【英文标题】:Audit table using "Envers" in Spring Hibernate java project 【发布时间】:2015-03-14 21:42:29 【问题描述】:我们需要使用 envers 来审计现有的表。我们没有hibernate.xml,而不是使用application-context.xml。我们正在通过“liquibase-changeset”创建模式,那么我如何通过@Entity 和@Audited 等注释创建。
我该如何解决这个问题?
我已经添加了休眠配置喜欢
<property name="hibernateProperties">
<props>
<prop key="hibernate.dialect">org.hibernate.dialect.mysqlInnoDBDialect</prop>
<prop key="hibernate.ejb.event.post-insert">org.hibernate.ejb.event.EJB3PostInsertEventListener,org.hibernate.envers.event.AuditEventListener</prop>
<prop key="hibernate.ejb.event.post-update">org.hibernate.ejb.event.EJB3PostUpdateEventListener,org.hibernate.envers.event.AuditEventListener</prop>
<prop key="hibernate.ejb.event.post-delete">org.hibernate.ejb.event.EJB3PostDeleteEventListener,org.hibernate.envers.event.AuditEventListener</prop>
<prop key="hibernate.ejb.event.pre-collection-update">org.hibernate.envers.event.AuditEventListener</prop>
<!-- <prop key="hibernate.ejb.event.pre-collection-remove">org.hibernate.envers.event.AuditEventListener</prop>
<prop key="hibernate.ejb.event.post-collection-recreate">org.hibernate.envers.event.AuditEventListener</prop> -->
<prop key="org.hibernate.envers.revision_field_name">REV</prop>
<prop key="org.hibernate.envers.revision_type_field_name">REVTYPE</prop>
<prop key="org.hibernate.envers.auditTablePrefix"></prop>
<prop key="org.hibernate.envers.auditTableSuffix">_HISTORY</prop>
<prop key="hibernate.hbm2ddl.auto">create</prop>
<prop key="hibernate.show_sql">true</prop>
</props>
</property>
在我的域类中添加了@Audited 注释
@Entity
@Audited
@Table(name="user")
public class User implements Serializable
但是这个配置删除了我现有的表
例如
Mydatabase
-----------
user
product
order_details
user_role
login
我的数据库中有 5 个表。运行我的应用程序后,它显示 3 个表。它不是创建“审计”表,而是删除现有表。
Mydatabase
-----------
user
product
order_details
如何在不触及现有表的情况下创建审计(_HISTORY)表???
【问题讨论】:
看这里 (***.com/questions/8573468/…),我前段时间遇到过类似的问题。 是映射到'user_role'和'login'表的对象@Entity
?
Yes Rohit.. 表用“@Entity”注释
仍然有问题...尚未创建审计表...如何创建审计表?需要在配置中添加什么?
@SST 你能让这个运行吗?请看下面我的回答。
【参考方案1】:
尝试从以下位置更改 DDL 策略:
<prop key="hibernate.hbm2ddl.auto">create</prop>
到:
<prop key="hibernate.hbm2ddl.auto">update</prop>
update DDL 生成策略不应删除任何现有表。
【讨论】:
感谢您的回复!!!我已经像这样将“创建”更改为“更新”,但仍然没有创建“审计”表...... :(如何创建审计表??休眠版本:3.6.3.Final,休眠环境版本:3.6 .3.Final 我错过了什么? 尝试将 EnversIntegrator.AUTO_REGISTER 添加为 false 我应该在哪里添加这个“EnversIntegrator.AUTO_REGISTER”设置为假?我的配置文件没有这一行... 你必须将 hibernate.listeners.envers.autoRegister 设置为 false 与其他属性 请阅读docs.jboss.org/hibernate/core/4.2/devguide/en-US/html/ch15.html 15.8。条件审计【参考方案2】:我正在开发一个使用带有 Hibernate 实现的 JPA 的项目,我们仅使用基于 Spring 上下文 xml 的配置(我们既不使用 persistence.xml)设法使 envers 正常工作。
我们的配置基于 Spring JPA 支持,但您可能会找到类似的解决方案:
<bean id="projectEntityManagerFactory" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
<property name="jpaVendorAdapter">
<bean class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter">
<property name="databasePlatform" value="org.hibernate.dialect.Oracle10gDialect" />
</bean>
</property>
<property name="packagesToScan">
<list>
<value>com.teimas.myproject.bo</value>
<value>com.teimas.myproject.bo.commons</value>
<value>com.teimas.myproject.bo.util</value>
</list>
</property>
<property name="persistenceUnitName" value="projectPU" />
<property name="jtaDataSource" ref="projectDataSourceTarget" />
<!-- Other ptops for hibernate config -->
<property name="jpaProperties" ref="jpaHibernateProperties" />
</bean>
<util:properties id="jpaHibernateProperties">
<prop key="hibernate.transaction.jta.platform">
org.hibernate.service.jta.platform.internal.JBossAppServerJtaPlatform
</prop>
<prop key="hibernate.dialect">org.hibernate.dialect.Oracle10gDialect</prop>
<!-- validate | update | create | create-drop -->
<prop key="hibernate.hbm2ddl.auto">validate</prop>
<prop key="hibernate.show_sql">false</prop>
<prop key="hibernate.format_sql">false</prop>
<prop key="javax.persistence.transactionType">JTA</prop>
<prop key="javax.persistence.validation.mode">AUTO</prop>
</util:properties>
关键是我们使用 Hibernate 对象作为 JPA 提供者:org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter 并且我们添加 packagesToScan 属性来告诉 hibernate 扫描这些包中的注释。所以 Hibernate 找到 Envers 和 Validation 注释,一切正常。
希望这会有所帮助。
【讨论】:
【参考方案3】:在 Liquibase 变更集中定义审计表定义,就像对任何其他表一样。
跳过 spring-hibernate ocnfiguration 中的 hibernate.hbm2ddl.auto
属性。这将指示 hibernate 不对架构做任何事情。
保持其余配置不变,这应该可以工作。
只需确保架构和配置中的审计表名称匹配即可。
链接到文档,详细说明如果架构是 generated 使用 ant,它是如何完成的
【讨论】:
同意。除了测试之外,不要将 hbm2ddl 用于任何事情。如果您从一个空模式开始,并且正确启用了 Envers,那么 hbm2ddl.auto=create 应该会生成审计表。这对我有用,但我使用的是 JPA persistence.xml(一个单独的用于测试的)。我使用生成的 DDL 并从中为真实数据库创建 Liquibase 更改集。【参考方案4】:我遇到了同样的问题,为了解决它,我按照以下步骤操作:
改变:
<prop key="hibernate.hbm2ddl.auto">create</prop>
到:
<prop key="hibernate.hbm2ddl.auto">update</prop>
如果您使用 ENVERS Hibernet-envers 3.5.5 或更高版本,您应该在应用程序上下文中进行此配置:
<property name="eventListeners">
<map>
<entry key="post-insert" >
<bean class="org.hibernate.envers.event.AuditEventListener" />
</entry>
<entry key="post-update">
<bean class="org.hibernate.envers.event.AuditEventListener" />
</entry>
<entry key="post-delete">
<bean class="org.hibernate.envers.event.AuditEventListener" />
</entry>
<entry key="pre-collection-update">
<bean class="org.hibernate.envers.event.AuditEventListener" />
</entry>
<entry key="pre-collection-remove">
<bean class="org.hibernate.envers.event.AuditEventListener" />
</entry>
<entry key="post-collection-recreate">
<bean class="org.hibernate.envers.event.AuditEventListener" />
</entry>
</map>
</property>
你必须像这样定义一个修订实体:
@Entity
@Table(name = "MY_REVINFO")
@RevisionEntity(MyRevisionListener.class)//@see next class
public class MyRevisionEntity
private static final long serialVersionUID =1L;
@Id
@GeneratedValue
@RevisionNumber
private int id;
@RevisionTimestamp
private long timestamp;
public int getId()
return id;
public void setId(int id)
this.id = id;
@Transient
public Date getRevisionDate()
return new Date(timestamp);
@Column(name = "USER_NAME")
private String userName;
@Column(name = "DATE_OPER")
private Date dateOperation;
public long getTimestamp()
return timestamp;
public void setTimestamp(long timestamp)
this.timestamp = timestamp;
public boolean equals(Object o)
if (this == o) return true;
if (!(o instanceof DefaultRevisionEntity)) return false;
DefaultRevisionEntity that = (DefaultRevisionEntity) o;
if (id != that.getId()) return false;
if (timestamp != that.getTimestamp()) return false;
return true;
public int hashCode()
int result;
result = id;
result = 31 * result + (int) (timestamp ^ (timestamp >>> 32));
return result;
public String getUserName()
return userName;
public void setUserName(String userName)
this.userName = userName;
public Date getDateOperation()
return dateOperation;
public void setDateOperation(Date dateOperation)
this.dateOperation = dateOperation;
public String toString()
return "DefaultRevisionEntity(id = " + id + ", revisionDate = " + DateFormat.getDateTimeInstance().format(getRevisionDate()) + ")";
在 application-context.xml 中添加这个新实体的映射:
<value>mypackage.MyRevisionEntity</value>
创建监听器(如果要保存用户名和操作时间,很有帮助):
public class MyRevisionListener implements RevisionListener
public void newRevision(Object revisionEntity)
MyRevisionEntity revision = (MyRevisionEntity) revisionEntity;
SecurityContext context = SecurityContextHolder.getContext();
Authentication authentication = context.getAuthentication();
UserDetails userDetails = (UserDetails) authentication.getPrincipal();
String userName="---";
if (userDetails != null)
userName=userDetails.getUsername();
else
userName="UNKNOWN";
revision.setUserName(userName);
revision.setDateOperation(new Date(revision.getTimestamp()));
清理、安装和运行您的应用程序。
如果问题仍然存在,请尝试升级您的 Envers 版本(Hibrenate-envers 和 Hibernate-core)
希望对您有所帮助。
【讨论】:
以上是关于在 Spring Hibernate java 项目中使用“Envers”审计表的主要内容,如果未能解决你的问题,请参考以下文章
在 Spring Boot 中配置 Hibernate 以忽略通过依赖项导入的标有 Entity 的某些类
spring 3.1 with hibernate 4 with spring security 3.1:如何确保包含所有依赖项以及要包含哪些标签?
在 Java 9 中删除 sun.misc.Unsafe 将破坏 Spring、Hibernate