【问题标题】:Audit table using "Envers" in Spring Hibernate java project在 Spring Hibernate java 项目中使用“Envers”审计表
【发布时间】: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)表???

【问题讨论】:

  • 看这里 (stackoverflow.com/questions/8573468/…),我前段时间遇到过类似的问题。
  • 是映射到'user_role'和'login'表的对象@Entity?
  • Yes Rohit.. 表用“@Entity”注释
  • 仍然有问题...尚未创建审计表...如何创建审计表?需要在配置中添加什么?
  • @SST 你能让这个运行吗?请看下面我的回答。

标签: java spring hibernate jpa hibernate-envers


【解决方案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 与其他属性
【解决方案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】:

    我遇到了同样的问题,为了解决它,我按照以下步骤操作:

    1. 改变:

      <prop key="hibernate.hbm2ddl.auto">create</prop>
      

    到:

        <prop key="hibernate.hbm2ddl.auto">update</prop>
    
    1. 如果您使用 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>
      
    2. 你必须像这样定义一个修订实体:

      @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()) + ")";
          }
      }
      
    3. 在 application-context.xml 中添加这个新实体的映射:

      <value>mypackage.MyRevisionEntity</value>
      
    4. 创建监听器(如果要保存用户名和操作时间,很有帮助):

      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()));
      }
      }
      
    5. 清理、安装和运行您的应用程序。

    6. 如果问题仍然存在,请尝试升级您的 Envers 版本(Hibrenate-envers 和 Hibernate-core)

    希望对您有所帮助。

    【讨论】:

      猜你喜欢
      • 2023-03-24
      • 1970-01-01
      • 1970-01-01
      • 2018-04-18
      • 2013-05-06
      • 1970-01-01
      • 2017-07-09
      • 2018-09-19
      • 2015-08-20
      相关资源
      最近更新 更多