在我的用例中,有一个Job,这个Job有评论。由于您无法编辑评论,因此我不想审核此实体。 这是代码:
@Audited(withModifiedFlag = true)
@Entity
@Table(name = "JOB")
public class Job {
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
@Column(name = "id")
private Integer id;
@Audited(targetAuditMode = RelationTargetAuditMode.NOT_AUDITED)
@OneToMany(cascade = CascadeType.ALL, orphanRemoval = true)
@JoinColumn(name = "j_id")
private List<Comment> comments;
}
@Entity
@Table(name = "COMMENT")
public class Comment {
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
@Column(name = "id")
private Integer id;
@Column(name = "title")
private String title;
@Column(name = "text")
private String text;
}
现在我希望能够获取与comments
相关的所有修改。
当然Hibernate不会生成COMMENT_AUD表。但是它会生成一个JOB_COMMENT_AUD表。
如何从AuditReader
获取相应的评论实体?我只能使用AuditReader读取Job实体。或者换句话说:我需要使用AuditReader访问JOB_COMMENT_AUD条目。
不知何故,必须可以使用AuditReader获取相应的Comment实体。为什么hibernate还应该将关系审核到自动生成的JOB_COMMENT_AUD表中?
答案 0 :(得分:2)
首先了解RelationalTargetAuditMode.NOT_AUDITED
的作用非常重要。
此批注将使Envers生成一个连接表,该连接表维护被审计实体Job
与Comment
实体的ORM数据表之间主键关系的外键。
换句话说,Envers不会复制Comment
实体的审计模式中的任何列,而只会捕获主键,以便在填充审计的Job
实例时,它知道如何正确设置Comment
s的集合。
从AuditReader
开始,只能查询Job
种类型。这是因为您只标记了要审核的Job
类型,而不是Comment
类型。但这并不意味着当您获得Comment
的审核实例时,您无法获取关联的Job
。
final AuditReader auditReader = AuditReaderFactory.get( entityManager );
// Get the first revision of Job with id jobId
// This Job has 2 comments, so here we can get them easily.
final Job job = auditReader.find( Job.class, jobId, 1 );
assertEquals( 2, job.getComments().size() );
assertEquals( "Hello World", job.getComments().get( 0 ).getText() );
assertEquals( "Goodbye World", job.getComments().get( 1 ).getText() );
Envers使用代理包装您的Comment
集合,以便在您的代码首次尝试访问它时,它会检查该集合是否已初始化。如果没有,它将根据专门的查询填充集合,该查询知道如何获取有关当前Job
实体,Job_Comment_AUD
表和基本Comment
表的修订数据为您的实体加载实体数据。
换句话说,代理初始化会为您触发这样的查询:
SELECT c.*
FROM Comment c,
Job_Comment_AUD jc
WHERE jc.job_id = :jobId
AND jc.revision = :jobRevision
AND jc.comment_id = c.id
美观是您的代码不需要使用Hibernate Session
或JPA EntityManager
执行任何特定的提取或查询。当您调用job.getComments()
集合时,Envers会为您无缝处理。