I have an entity with a reference to another entity, something like this:
@Entity(name = "MyCustomEntity")
@Table(name = "my_custom_entity")
public class MyCustomEntity {
@Id
Integer id;
@ManyToOne
@JoinColumn(name = "profile_id")
OtherEntity other;
}
As it turns out, business logic dictates that OtherEntity should not be mutable in this context. Since you can still change the entity outside this context, I thought it was easiest to change the reference from MyCustomEntity to an Envers revision.
I could replace the reference with this snippet:
@Entity(name = "MyCustomEntity")
@Table(name = "my_custom_entity")
public class MyCustomEntity {
@Id
Integer id;
Integer otherId;
Integer revision;
}
OtherEntity getOther(MyCustomEntity entity) throws Exception {
return auditReader.find(OtherEntity.class, entity.otherId, entity.revision);
}
But I'd lose a couple of Hibernate features that I'd rather have.
Is there a better way to reference an Envers revision?
Based on the fact you simply want to enforce immutability with the relationship between the two entities, why not simply make use of the
@Immutableannotation here rather than trying to manipulate this through your model.But it's important to understand that
Immutablein this content applies solely to ORM.Lets say you perform the following actions
MyCustomEntityrevision pointing toOtherEntity.OtherEntity(now has a higher revision number thanMyCustomEntity)MyCustomEntity(now has a higher revision number thanOtherEntity)MyCustomEntitywith latest revision.That latest revision will point to the
OtherEntitywith modifications made in step 2. The immutability annotation simply doesn't allow changing the FK reference.Does that solve your issue?
UPDATE
That is precisely how Envers works.
The
MyCustomEntitywill only return the related association with a revision number that is equal-to or less-than its queried revision.That means if you modify
OtherEntityand then queryMyCustomEntity, the returned instance ofOtherEntitywould not contain those recent changes.The only time that
MyCustomEntitywould return the latest snapshot of theOtherEntityassociation would be ifMyCustomEntityis modified in the same transaction or a future transaction afterOtherEntity.Associations are always returned with the associated entity-type having a revision number than is
<=the queried entity's revision number.If you're changing both, then the order in which you perform those changes will play into what snapshot the relationship will return in audit queries.
If you're goal is to somehow pin a revision, there really isn't a good logical way to do that, at least not within the same transaction boundary anyway given how Envers performs its logic in a pre-commit transaction callback.