Reputation: 457
I am using hibernate envers for auditing.
I have two entity classes, A and B. There is a one-to-one relationship between them. So this creates two audit tables A_aud and B_aud. Creation/Updates for both is done through one screen.
So my requirement is that whenever there is a change in any table of both (in any field of them), I need an audit entry in both tables.
How can I achieve this?
And this how I defined the mapping on both sides
public class A implements Serializable {
private B b;
@OneToOne(mappedBy = "a", cascade = CascadeType.ALL, fetch = FetchType.LAZY, optional = false)
public B getB() {
return b;
}
public void setB(B b) {
this.b = b;
}
}
public class B implements Serializable{
private A a;
@OneToOne(cascade = CascadeType.ALL, fetch = FetchType.LAZY)
@JoinColumn(name = "A_ID", referencedColumnName = "id",nullable = false)
public A getA() {
return a;
}
public void setA(A a) {
this.a = a;
}
}
Upvotes: 1
Views: 2267
Reputation: 21103
Whenever two objects are associated, such as in the case with your @OneToOne
, changes to either side of the relationship will not cascade an audit of the other side of that relationship unless you:
B
to a different instance of A
From a simple Change Data Capture (CDC) perspective, these rules make sense. What I mean is the attributes on the associated entity that wasn't modified in your screen in any meaningful way does not justify an audit row, so we only capture the entity instance on the side which actually had any changes detected.
In a complex domain model, we have multitudes of relationships between objects. Just imagine the sheer number of audit rows generated if we propagated those change events across relationship boundaries. You could easily have a situation where a change of a basic string attribute would lead to the auditing of your entire object graph of entities related to the changed entity.
You have a couple ways you can accomplish what you want:
There is an entire section in the documentation on Conditional Auditing. Its original purpose was to control whether certain changes on audit entities should allow an entity to be recorded, but you could also use it to navigate very specific entity associated and force work unit audit operations on related entities. This is an expert approach and not one I recommend for users who are not familiar and how it operates. In 6.0, I'm looking to simplify this in some ways to make this less intrusive than what users must currently do.
The simplest of ways is to do (2). For this to work, you would add a new field on both entities that would store something such as a timestamp value. Whenever a change happens to either entity in your UI, you would set the timestamp for both entities which effectively will force Envers to audit both entities in the same transaction, accomplishing precisely what you want.
This is something that users bring up frequently, so I've created HHH-13362 where we can have a more detailed discussion on how to best develop and improve on this in a less intrusive way.
Upvotes: 2