如何在Hibernate中维护表的历史记录

为了维护数据库的历史记录或跟踪数据库表行的修改,我们创建了一个版本表,其中包含与原始表相同的字段。每当原始表被更改时,我们都会在版本表中创建另一个条目。 因此,对于每个更新查询,我们都必须在版本表中编写一个插入查询。 休眠中有一个模块可以管理对象的简单审核,而我们不必自己编写单独的插入查询。

Hibernate Envers提供了内置的机制来维护数据库中对象的历史记录。 Envers是Hibernate的库,它将帮助我们轻松实现审核功能。 这是由Adam Warski创建的。 从Hibernate 3.5开始,Envers作为Hibernate核心模块包含在内。 让我们举一个例子,说明如何使用Envers维护对象的历史记录。

这是Envers的pom依赖关系(版本将与您的休眠核心和实体管理器相同):

<dependency>  <groupId>org.hibernate</groupId> 
  <artifactId>hibernate-envers</artifactId> 
  <version>4.0.1.Final</version> 
</dependency>

您必须在hibernate.cfg.xml中配置侦听器。

<mapping class="com.javaroots.model.User" />

  <listener class="org.hibernate.envers.event.AuditEventListener" type="post-insert"/>
  <listener class="org.hibernate.envers.event.AuditEventListener" type="post-update"/>
  <listener class="org.hibernate.envers.event.AuditEventListener" type="post-delete"/>
  <listener class="org.hibernate.envers.event.AuditEventListener" type="pre-collection-update"/>
  <listener class="org.hibernate.envers.event.AuditEventListener" type="pre-collection-remove"/>
  <listener class="org.hibernate.envers.event.AuditEventListener" type="post-collection-recreate"/>

让我们以User类为例。 我们要跟踪用户字段的更新。 要为用户对象启用历史记录,我们需要使用@Audited批注。 如果在类级别上使用,则该类中的所有字段都将被视为可审计的,并且任何字段中的更改将在audit table中具有新条目。 如果我们希望某些字段不包含在历史记录中,则可以使用@NotAudited批注。 如果更改了NotAudited字段,那么审计表中将没有任何条目。这是用户类:

package com.javaroots.model;

import javax.persistence.Column;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.Entity;

import org.hibernate.envers.Audited;
import org.hibernate.envers.NotAudited;

/**
 * 
 * 
 * @author Abhishek Somani
 * 
 */
@Entity
@Audited
public class User {

 @Id
 @GeneratedValue(strategy = GenerationType.AUTO)
 private Long id;
 @Column(length = 20)
 private String firstName;
 @Column(length = 20)
 private String lastName;
 @Column(length = 20)
 @NotAudited
 private String password;

 public Long getId() {
  return id;
 }

 public void setId(Long id) {
  this.id = id;
 }

 public String getFirstName() {
  return firstName;
 }

 public void setFirstName(String firstName) {
  this.firstName = firstName;
 }

 public String getLastName() {
  return lastName;
 }

 public void setLastName(String lastName) {
  this.lastName = lastName;
 }

 public String getPassword() {
  return password;
 }

 public void setPassword(String password) {
  this.password = password;
 }

}

这是测试类,我们在其中创建用户表中的条目,然后更新它的field。

package com.javaroots.main;

import org.hibernate.Session;

import com.javaroots.model.User;
import com.javaroots.util.HibernateUtil;

public class HibernateTest {

public static void main(String[] args) {

        Session session = HibernateUtil.getSessionFactory().openSession();

        //one entry will be created in user table 
        //and audit entry created in user_aud table
        session.beginTransaction();

        User u = new User();
        u.setFirstName("Amitabh");
        u.setLastName("bachhan");
        u.setPassword("God");

        session.save(u);

        session.getTransaction().commit();

        session.beginTransaction();
        User amitabh = (User)session.get(User.class,1l);

        amitabh.setFirstName("Abhishek");

        session.getTransaction().commit();

        //no entry in audit table if we change password field
        //because this field is marked as @notAudited
        session.beginTransaction();
        amitabh = (User)session.get(User.class,1l);

        amitabh.setPassword("NotGod");

        session.getTransaction().commit();

   //get specific revision
        AuditReader reader = AuditReaderFactory.get(HibernateUtil.getSessionFactory().openSession());
        User abhishek = (User) reader.find(User.class, new Long(1), 2);
        System.out.println(abhishek.getFirstName() + " " + abhishek.getLastName());

        //get all revision

        List versions = reader.getRevisions(User.class, new Long(1));
        for (Number number : versions) {
          System.out.print(number + " ");
        }

    }

}

首先,在用户表中创建一个用户行。在user_aud中创建一个具有修订ID和用户表字段的行。 在revinfo表中使用修订ID和时间戳创建一行。 这两个条目由envers自动完成。 这是sql查询和表结构:

Hibernate: 
    insert 
    into
        User
        (firstName, lastName, password) 
    values
        (?, ?, ?)
Hibernate: 
    insert 
    into
        REVINFO
        (REVTSTMP) 
    values
        (?)
Hibernate: 
    insert 
    into
        User_AUD
        (REVTYPE, firstName, lastName, id, REV) 
    values
        (?, ?, ?, ?, ?)
Hibernate: 
    update
        User 
    set
        firstName=?,
        lastName=?,
        password=? 
    where
        id=?
Hibernate: 
    insert 
    into
        REVINFO
        (REVTSTMP) 
    values
        (?)
Hibernate: 
    insert 
    into
        User_AUD
        (REVTYPE, firstName, lastName, id, REV) 
    values
        (?, ?, ?, ?, ?)
Hibernate: 
    update
        User 
    set
        firstName=?,
        lastName=?,
        password=? 
    where
        id=?
Hibernate: 
    select
        user_aud0_.id as id4_,
        user_aud0_.REV as REV4_,
        user_aud0_.REVTYPE as REVTYPE4_,
        user_aud0_.firstName as firstName4_,
        user_aud0_.lastName as lastName4_ 
    from
        User_AUD user_aud0_ 
    where
        user_aud0_.REV=(
            select
                max(user_aud1_.REV) 
            from
                User_AUD user_aud1_ 
            where
                user_aud1_.REV<=? 
                and user_aud0_.id=user_aud1_.id
        ) 
        and user_aud0_.REVTYPE<>? 
        and user_aud0_.id=?
Abhishek bachhan
Hibernate: 
    select
        user_aud0_.REV as col_0_0_ 
    from
        User_AUD user_aud0_ cross 
    join
        REVINFO defaultrev1_ 
    where
        user_aud0_.id=? 
        and user_aud0_.REV=defaultrev1_.REV 
    order by
        user_aud0_.REV asc
mysql> select * from user;
+----+-----------+----------+---------------+
| id | firstName | lastName | password      |
+----+-----------+----------+---------------+
|  1 | Amitabh   | bachchan    | God|
+----+-----------+----------+---------------+
1 row in set (0.03 sec)

mysql> select * from user_aud;
+----+-----+---------+-----------+----------+
| id | REV | REVTYPE | firstName | lastName |
+----+-----+---------+-----------+----------+
|  1 |   1 |       0 | Amitabh   | bachchan    |
+----+-----+---------+-----------+----------+
1 row in set (0.00 sec)

mysql> select * from revinfo;
+-----+---------------+
| REV | REVTSTMP      |
+-----+---------------+
|   1 | 1375956506278|
+-----+---------------+
1 row in set (0.00 sec)
mysql> select * from user;
+----+-----------+----------+----------------+
| id | firstName | lastName | password       |
+----+-----------+----------+----------------+
|  1 | Amitabh   | bachchan| NotGod |
+----+-----------+----------+----------------+
1 row in set (0.00 sec)

mysql> select * from user_aud;
+----+-----+---------+-----------+----------+
| id | REV | REVTYPE | firstName | lastName |
+----+-----+---------+-----------+----------+
|  1 |   1 |       0 | Amitabh   | bachchan |
|  1 |   2 |       1 | Abhishek  | bachchan|
+----+-----+---------+-----------+----------+
2 rows in set (0.00 sec)

mysql> select * from revinfo;
+-----+---------------+
| REV | REVTSTMP      |
+-----+---------------+
|   1 | 1375956506278|
|   2 | 1375956506328|
+-----+---------------+
2 rows in set (0.00 sec)


翻译自: https://www.javacodegeeks.com/2013/09/how-to-maintain-history-of-tables-in-hibernate.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值