如何读取标记NOT_AUDITED的关联修改并获取Comment审计数据?
获取关联Comment的Hibernate审计记录
你的场景里,因为给Job.comments标注了@Audited(targetAuditMode = RelationTargetAuditMode.NOT_AUDITED),Hibernate只会审计关联关系的变化(比如添加/删除Comment到Job的操作),而不会审计Comment实体本身,所以生成了JOB_COMMENT_AUD关联审计表,而非COMMENT_AUD。下面两种方法可以帮你获取相关的修改记录:
方法一:通过AuditReader查询Job的修订记录,提取Comment关联变化
既然Job本身是审计的,你可以查询Job的所有修订版本,然后对比不同版本中comments集合的差异,找出哪些Comment被添加或移除了。
示例代码:
// 获取AuditReader实例 AuditReader auditReader = AuditReaderFactory.get(entityManager); // 获取目标Job的所有修订号 List<Number> revisions = auditReader.getRevisions(Job.class, targetJobId); // 遍历每个修订版本,提取对应的comments集合 Job previousJob = null; for (Number rev : revisions) { Job currentJob = auditReader.find(Job.class, targetJobId, rev); List<Comment> currentComments = currentJob.getComments(); if (previousJob != null) { List<Comment> previousComments = previousJob.getComments(); // 找出新增的Comment:current有但previous没有的 List<Comment> addedComments = currentComments.stream() .filter(c -> !previousComments.contains(c)) .collect(Collectors.toList()); // 找出删除的Comment:previous有但current没有的 List<Comment> removedComments = previousComments.stream() .filter(c -> !currentComments.contains(c)) .collect(Collectors.toList()); // 处理新增/删除记录,比如打印或存储 System.out.println("修订号 " + rev + " 新增Comment:" + addedComments); System.out.println("修订号 " + rev + " 删除Comment:" + removedComments); } previousJob = currentJob; }
这种方法的优势是不需要额外的实体映射,直接用Hibernate Envers的API操作,但只能获取到关联关系的变化(增删Comment),无法获取Comment内容的修改(不过你提到Comment不可编辑,这刚好符合需求)。
方法二:直接映射并查询JOB_COMMENT_AUD表
Hibernate生成的JOB_COMMENT_AUD表存储了关联关系的审计记录,你可以创建一个实体类直接映射这个表,然后用JPA或原生SQL查询。
步骤1:创建映射实体
@Entity @Table(name = "JOB_COMMENT_AUD") // 确保表名和Hibernate生成的一致 public class JobCommentAudit { @Id @Column(name = "rev") private Integer revisionId; @Column(name = "revtype") private Integer revisionType; // revtype含义:0=新增关联,1=修改关联(你的场景不会出现),2=删除关联 @Column(name = "j_id") private Integer jobId; @Column(name = "id") private Integer commentId; // Getter和Setter方法 }
步骤2:查询审计记录
用JPA查询:
List<JobCommentAudit> auditRecords = entityManager.createQuery( "SELECT jca FROM JobCommentAudit jca WHERE jca.jobId = :jobId", JobCommentAudit.class ) .setParameter("jobId", targetJobId) .getResultList(); // 遍历处理记录 for (JobCommentAudit record : auditRecords) { String action = switch (record.getRevisionType()) { case 0 -> "添加了Comment"; case 2 -> "删除了Comment"; default -> "未知操作"; }; System.out.println("修订号 " + record.getRevisionId() + ":" + action + ",Comment ID:" + record.getCommentId()); // 如果需要Comment的详细信息,可以通过commentId查询Comment表 Comment comment = entityManager.find(Comment.class, record.getCommentId()); }
或者用原生SQL查询(适合不想创建映射实体的情况):
List<Object[]> rawRecords = entityManager.createNativeQuery( "SELECT rev, revtype, j_id, id FROM JOB_COMMENT_AUD WHERE j_id = ?" ) .setParameter(1, targetJobId) .getResultList(); for (Object[] record : rawRecords) { Integer rev = (Integer) record[0]; Integer revType = (Integer) record[1]; Integer jobId = (Integer) record[2]; Integer commentId = (Integer) record[3]; // 处理逻辑同上 }
这种方法更直接,能快速获取所有关联操作的审计记录,适合需要批量处理或不需要Job其他审计信息的场景。
内容的提问来源于stack exchange,提问作者kemal89
相关产品推荐
相关产品推荐

