I use Hibernate Envers to audit my entities.
I have one audited entity, Foo
, which has a List<Bar>
as properties. However, I don't want to audit the Bar
entities. Thus, I wrote that:
@Entity @Audited public class Foo { @JoinTable(name = "T_FOO_BAR", joinColumns = @JoinColumn(name = "FOO_ID"), inverseJoinColumns = @JoinColumn(name = "BAR_ID")) @ManyToMany(cascade = PERSIST) @Audited(targetAuditMode = RelationTargetAuditMode.NOT_AUDITED) public List<Bar> getBars() { return bars; } }
Now, I want to retrieve a revision of Foo
:
AuditReader reader = AuditReaderFactory.get(getEntityManager()); Foo revision = (Foo) reader.createQuery().forEntitiesAtRevision(Foo.class, 42).getSingleResult();
Unfortunately, when I want to retrieve all the data (i.e. when it lazy loads the bars
), I get the error ORA-00942: table or view does not exist
, as it tried to query:
select ... from T_FOO_BAR_AUD x, T_BAR y where ...
I though that using @Audited(targetAuditMode = RelationTargetAuditMode.NOT_AUDITED)
, Hibernate Envers would keep the links with the Bar
items of the current entity.
So how can I solve my problem, without having to explicitely audit the tables T_BAR
and T_FOO_BAR
(the join table)? In others words, when I retrieve the list of bars
from my revision entity, I get the list of bars
from my current entity (as the links between Foo
and Bar
are not audited).
Thanks.
Hibernate Envers provides a very simple solution for CDC (Change Data Capture). It uses the Hibernate Event system to intercept all entity state transitions and audit them. The database transaction will roll back and both the actual changes and the audit log is rolled back.
The Envers module is a core Hibernate model that works both with Hibernate and JPA. In fact, you can use Envers anywhere Hibernate works whether that is standalone, inside WildFly or JBoss AS, Spring, Grails, etc. The Envers module aims to provide an easy auditing / versioning solution for entity classes.
REVINFO. This table stores the revision information. By default, Hibernate persists only the revision number as an integer and the creation timestamp as a long. 1.
It looks like you're using @Audited(targetAuditMode = RelationTargetAuditMode.NOT_AUDITED)
when you should be using @NotAudited
in your case.
RelationTargetAuditMode.NOT_AUDITED
will simply not audit the target entity. It will still try to audit the List<Bar>
property of Foo
, and thus the join table.
From the docs:
If you want to audit a relation, where the target entity is not audited (that is the case for example with dictionary-like entities, which don't change and don't have to be audited), just annotate it with
@Audited(targetAuditMode = RelationTargetAuditMode.NOT_AUDITED)
. Then, when reading historic versions of your entity, the relation will always point to the "current" related entity.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With