I've been using Hibernate Envers 3.6 quite happily for some time. However I've come across an issue with ordered lists which seems to cause Envers to fail.
We have a class A with a List of B, mapped one-to-many in e.g., in class A
@OneToMany(mappedBy = "A", cascade = CascadeType.ALL, orphanRemoval = true)
public List<B> getB() {
return this.B;
}
When I retrieve a revision, I load up the appropriate instance of A, then explicitly initialize the collection of Bs: E.g.,
for (B b: rvision.getB()){
b.getClass();// init fields
}
Recently though we needed to add an 'orderColumn' annotation on the getB() method to ensure consistent ordering of the list in the DB.
E.g.,
@OneToMany(mappedBy = "A", cascade = CascadeType.ALL, orphanRemoval = true)
@OrderColumn(name="columnIndex")
public List<B> getB() {
return this.B;
}
This completely breaks the collection initialization in Envers, failing with a null pointer exception:
java.lang.NullPointerException
at org.hibernate.envers.entities.mapper.relation.lazy.initializor.ListCollectionInitializor.addToCollection(ListCollectionInitializor.java:81)
at org.hibernate.envers.entities.mapper.relation.lazy.initializor.ListCollectionInitializor.addToCollection(ListCollectionInitializor.java:39)
at org.hibernate.envers.entities.mapper.relation.lazy.initializor.AbstractCollectionInitializor.initialize(AbstractCollectionInitializor.java:67)
at org.hibernate.envers.entities.mapper.relation.lazy.proxy.CollectionProxy.checkInit(CollectionProxy.java:50)
at org.hibernate.envers.entities.mapper.relation.lazy.proxy.CollectionProxy.size(CollectionProxy.java:55)
etc....
We have isolated this into a unit test; toggling the OrderColumn annotation is sufficient to cause this problem. The OrderColumn is working fine with regular Hibernate.
The problem seems to stem from line 47 of org.hibernate.envers.entities.mapper.relation.component.MiddleSimpleComponentMapper:
return ((Map<String, Object>) data.get(verEntCfg.getOriginalIdPropName())).get(propertyName);
Basically the 'propertyName' it's looking for is called 'mapKey' and the lookup returns null when it shouldn't. This isn't a property of my objects so it must be some internal Envers property.
If anyone have a clue what is going on, I'd be very grateful! Thanks Richard
We ran into this issue with Hibernate Envers 4.x. The solution for us was to use the @AuditMappedBy
annotation to identify the order column for Envers. As shown in the example here it is necessary to map the order column value into a field on the referenced entity to make it all work.