审核表使用" Envers"在Spring Hibernate java项目中

时间:2015-01-16 09:58:04

标签: java spring hibernate jpa hibernate-envers

我们需要使用envers审核现有表。我们没有hibernate.xml,而不是使用application-context.xml。我们正在通过" liquibase-changeset"创建模式,然后如何通过@Entity和@Audited等注释创建。

如何解决此问题?

我添加了hibernate配置

<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 {

但是这个配置删除了我现有的表

e.g

Mydatabase
-----------

user
product
order_details
user_role
login

我的数据库中有5个表。运行我的应用程序后,它显示3个表。而不是创建&#34;审计&#34;表,它删除现有表。

 Mydatabase
  -----------

  user
  product
  order_details

如何在不触及现有表的情况下创建审计(_HISTORY)表???

4 个答案:

答案 0 :(得分:3)

在Liquibase变更集中,定义审计表定义,就像对任何其他表一样。

在spring-hibernate ocnfiguration中跳过hibernate.hbm2ddl.auto属性。这将指示hibernate不对架构做任何事情。

保持其余的配置,这应该有效。

只需确保架构和配置中的审计表名称匹配。

链接到文档,详细说明如何使用ant

在案例架构中完成generated

答案 1 :(得分:3)

我遇到了同样的问题,要解决它,我按照接下来的步骤进行操作:

  1. 更改:

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

        <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)

    7. 希望得到这个帮助。

答案 2 :(得分:1)

尝试更改DDL策略:

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

为:

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

更新 DDL生成策略不应删除任何现有表。

答案 3 :(得分:0)

我正在使用带有Hibernate实现的JPA开发一个项目,并且我们设法使用基于Spring上下文xml的配置使envers工作没有太多问题(我们都不使用persistence.xml)。

我们的配置基于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 anotations,一切正常。

希望这有帮助。