如何在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)@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)
- 下载源代码
翻译自: https://www.javacodegeeks.com/2013/09/how-to-maintain-history-of-tables-in-hibernate.html
如何在Hibernate中维护表的历史记录相关推荐
- rdp连接工具_如何在Windows10中清除RDP连接历史记录?
如何在Windows中清除RDP连接历史记录? 内置的Windows远程桌面连接(RDP)客户端(mstsc.exe)保存每次成功连接到远程计算机后的远程计算机名(或IP地址)和用于登录的用户名.在下 ...
- 抓取html表单验证码,如何在jquery中利用表单获取短信验证码
如何在jquery中利用表单获取短信验证码 发布时间:2021-02-18 15:42:54 来源:亿速云 阅读:88 作者:Leah 这期内容当中小编将会给大家带来有关如何在jquery中利用表单获 ...
- php接收表单图片,如何在PHP中获取表单图片数据
这是我的HTML,用于发布带图片的广告. {% for count in 1..10 %} {% endfor %} 这是我的轮廓仪功能 public function insertProduct( ...
- java hibernate 自定义排序_java – 如何在hibernate中对关联表进行排序?
根据JPA规范: The property or field name must correspond to that of a persistent property or field of the ...
- hibernate mysql 外键_如何在hibernate中设置关联会在数据库中生成外键
hibernate学习笔记(三) hibernate的一些杂记:1.sessionFactory的用法:SessionFactory是线程安全的,构造 SessionFactory 很消耗资源sess ...
- nosql简答什么是最终一致性_最终一致性 – 如何在NoSQL中维护非规范化一致性?...
假设我有两个集合,每个集合的值彼此独立,但每个集合彼此相关.他们是照片和用户.用户和照片之间存在一对多的关系. 非规范化数据的一个例子: users: { "id": " ...
- 如何在Word中的表上添加边框或更改边框
By default, when you insert a table, there is a simple, black border around all the cells in the tab ...
- Hibernate 中出现表名(XXX) is not mapped 问题
当你们遇到这个问题,只能说是没有好好理解Hibernate.当我们执行如下语句的时候: StudentDaoimpl: public int selectAllQingJiaDanCounts(Str ...
- mongodb和mysql中自动增长id_如何在java中维护MongoDB的_id字段的自动增长
_id字段是MongoDB中一个特殊的字段,它的类型为BSON ObjectId.它是每条记录的第一个属性,并且该属性值必须唯一. BSON ObjectId长12个字节,包含4字节的时间戳.3字节的 ...
最新文章
- c# 如何将字符串中用,分开的数字分别存入数组中
- JavaScript 技术篇-js获取表格元素tr、th、td相对于父节点的索引。
- applicationSettings设置和appsttings
- AI玩微信跳一跳的正确姿势:一不小心就超越了最高分,瞬间称霸了朋友圈~
- DAGNN:有向无环图神经网络
- c语言中注释部分二侧分界符为,C语言常见复习题(选择填空)及参考答案
- dat文本导入mysql_mysql学习笔记(九) 增删改查的优化
- Telerik RadGridView 右键菜单如何设置?
- 小米改鸿蒙系统,小米、OV傻眼 魅族要用鸿蒙系统!
- python不能安装的问题_无法安装pythoncolam
- 【USACO】回文平方数
- BZOJ1027 [JSOI2007]合金 【计算几何 + floyd】
- 5款 Mac 常用PDF阅读和编辑软件推荐
- 基于stm32的无线多点温度采集系统设计
- 数据可视化专属配色方案
- 安装确认书模板_房屋租赁合同模板及审查要点
- mongoose报错Cast to ObjectId failed for value
- selected和checked区别
- 第2章第24节:文字云:实现非常有创意的文字组织方式 [PowerPoint精美幻灯片实战教程]
- 交叉熵损失函数以及softmax损失函数
热门文章
- 散列算法,Remal使用散列算法
- 专属微信二维码python制作_如何利用Python制作简单的公众号二维码关注图
- javabean与json转换(fastjson与jackson两个版本)
- 关于es查询dsl的filter与must,term与match的区别
- XML——使用 XPath来定位信息+使用命名空间
- java日志——基本日志+高级日志
- graalvm_GraalVM上的Picocli:极快的命令行应用程序
- java heroku_使用Spring Boot和Heroku在20分钟内完成Java的单点登录
- 枚举重名_举重设计模式示例
- 如何通过示例使用Java中的Exchanger