The problem boils down to how the BasicCollectionMapper detects the difference between an ADD, a DEL, and if an element in the collection simply hasn't changed. At the moment, we do this by delegating the check to the element's Type. There are essentially 3 types of collections we need to be concerned about:
- Collections of basic-types
- Collections of embeddables
- Collections of entities
For both (1) and (2), the logic the mapper uses works fine. This is because the associated Type for these two scenarios perform both a reference-equality and value-equality check. Where the logic begins to break down is with (3) as you've noticed. The code currently delegates to EntityType but ORM only considers two entity instances to be identical if and only if they are reference-equal. In your example, the values are actually not reference equal and therefore the change delta logic results in both an ADD and DEL entry. For (3), the audit table merely holds a reference to the owning entity id and the referenced entity id. So what I believe we can do is rather than delegate the check for (3) to the EntityType, we could instead delegate it to the entity's identifier Type instead which would either be a basic-type or a composite-type, which takes us right back to the same type of check which we use for either scenario (1) or (2). For Envers 5.x, I believe this is a decent compromise. This allows us to fix the underlying problem in such a way that we do not need to impose any schema alterations for users mid major release to deal with the the fact that REVTYPE is not part of the collection table's primary key. For Envers 6, I'll enforce REVTYPE being part of the primary-key with a backward compatibility configuration option that can be enabled so that existing applications can continue to support legacy behavior until they can manually modify their schema accordingly. |