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

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)@NotAuditedprivate 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 tablesession.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 @notAuditedsession.beginTransaction();amitabh = (User)session.get(User.class,1l);amitabh.setPassword("NotGod");session.getTransaction().commit();//get specific revisionAuditReader 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 revisionList 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 intoUser(firstName, lastName, password) values(?, ?, ?)
Hibernate: insert intoREVINFO(REVTSTMP) values(?)
Hibernate: insert intoUser_AUD(REVTYPE, firstName, lastName, id, REV) values(?, ?, ?, ?, ?)
Hibernate: updateUser setfirstName=?,lastName=?,password=? whereid=?
Hibernate: insert intoREVINFO(REVTSTMP) values(?)
Hibernate: insert intoUser_AUD(REVTYPE, firstName, lastName, id, REV) values(?, ?, ?, ?, ?)
Hibernate: updateUser setfirstName=?,lastName=?,password=? whereid=?
Hibernate: selectuser_aud0_.id as id4_,user_aud0_.REV as REV4_,user_aud0_.REVTYPE as REVTYPE4_,user_aud0_.firstName as firstName4_,user_aud0_.lastName as lastName4_ fromUser_AUD user_aud0_ whereuser_aud0_.REV=(selectmax(user_aud1_.REV) fromUser_AUD user_aud1_ whereuser_aud1_.REV<=? and user_aud0_.id=user_aud1_.id) and user_aud0_.REVTYPE<>? and user_aud0_.id=?
Abhishek bachhan
Hibernate: selectuser_aud0_.REV as col_0_0_ fromUser_AUD user_aud0_ cross joinREVINFO defaultrev1_ whereuser_aud0_.id=? and user_aud0_.REV=defaultrev1_.REV order byuser_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)
  • 下载源代码
参考: Java,J2EE和Server博客上的JCG合作伙伴 Abhishek Somani提供了如何在Hibernate中维护表的历史记录 。

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

如何在Hibernate中维护表的历史记录相关推荐

  1. rdp连接工具_如何在Windows10中清除RDP连接历史记录?

    如何在Windows中清除RDP连接历史记录? 内置的Windows远程桌面连接(RDP)客户端(mstsc.exe)保存每次成功连接到远程计算机后的远程计算机名(或IP地址)和用于登录的用户名.在下 ...

  2. 抓取html表单验证码,如何在jquery中利用表单获取短信验证码

    如何在jquery中利用表单获取短信验证码 发布时间:2021-02-18 15:42:54 来源:亿速云 阅读:88 作者:Leah 这期内容当中小编将会给大家带来有关如何在jquery中利用表单获 ...

  3. php接收表单图片,如何在PHP中获取表单图片数据

    这是我的HTML,用于发布带图片的广告. {% for count in 1..10 %} {% endfor %} 这是我的轮廓仪功能 public function insertProduct( ...

  4. java hibernate 自定义排序_java – 如何在hibernate中对关联表进行排序?

    根据JPA规范: The property or field name must correspond to that of a persistent property or field of the ...

  5. hibernate mysql 外键_如何在hibernate中设置关联会在数据库中生成外键

    hibernate学习笔记(三) hibernate的一些杂记:1.sessionFactory的用法:SessionFactory是线程安全的,构造 SessionFactory 很消耗资源sess ...

  6. nosql简答什么是最终一致性_最终一致性 – 如何在NoSQL中维护非规范化一致性?...

    假设我有两个集合,每个集合的值彼此独立,但每个集合彼此相关.他们是照片和用户.用户和照片之间存在一对多的关系. 非规范化数据的一个例子: users: { "id": " ...

  7. 如何在Word中的表上添加边框或更改边框

    By default, when you insert a table, there is a simple, black border around all the cells in the tab ...

  8. Hibernate 中出现表名(XXX) is not mapped 问题

    当你们遇到这个问题,只能说是没有好好理解Hibernate.当我们执行如下语句的时候: StudentDaoimpl: public int selectAllQingJiaDanCounts(Str ...

  9. mongodb和mysql中自动增长id_如何在java中维护MongoDB的_id字段的自动增长

    _id字段是MongoDB中一个特殊的字段,它的类型为BSON ObjectId.它是每条记录的第一个属性,并且该属性值必须唯一. BSON ObjectId长12个字节,包含4字节的时间戳.3字节的 ...

最新文章

  1. c# 如何将字符串中用,分开的数字分别存入数组中
  2. JavaScript 技术篇-js获取表格元素tr、th、td相对于父节点的索引。
  3. applicationSettings设置和appsttings
  4. AI玩微信跳一跳的正确姿势:一不小心就超越了最高分,瞬间称霸了朋友圈~
  5. DAGNN:有向无环图神经网络
  6. c语言中注释部分二侧分界符为,C语言常见复习题(选择填空)及参考答案
  7. dat文本导入mysql_mysql学习笔记(九) 增删改查的优化
  8. Telerik RadGridView 右键菜单如何设置?
  9. 小米改鸿蒙系统,小米、OV傻眼 魅族要用鸿蒙系统!
  10. python不能安装的问题_无法安装pythoncolam
  11. 【USACO】回文平方数
  12. BZOJ1027 [JSOI2007]合金 【计算几何 + floyd】
  13. 5款 Mac 常用PDF阅读和编辑软件推荐
  14. 基于stm32的无线多点温度采集系统设计
  15. 数据可视化专属配色方案
  16. 安装确认书模板_房屋租赁合同模板及审查要点
  17. mongoose报错Cast to ObjectId failed for value
  18. selected和checked区别
  19. 第2章第24节:文字云:实现非常有创意的文字组织方式 [PowerPoint精美幻灯片实战教程]
  20. 交叉熵损失函数以及softmax损失函数

热门文章

  1. 散列算法,Remal使用散列算法
  2. 专属微信二维码python制作_如何利用Python制作简单的公众号二维码关注图
  3. javabean与json转换(fastjson与jackson两个版本)
  4. 关于es查询dsl的filter与must,term与match的区别
  5. XML——使用 XPath来定位信息+使用命名空间
  6. java日志——基本日志+高级日志
  7. graalvm_GraalVM上的Picocli:极快的命令行应用程序
  8. java heroku_使用Spring Boot和Heroku在20分钟内完成Java的单点登录
  9. 枚举重名_举重设计模式示例
  10. 如何通过示例使用Java中的Exchanger