kristofferlundberg/hibernate-core — comment on commit e88029194ad34f403e8f3fbe80f56e09678a34d4
File:  line 0
By kristofferlundberg:

@ElementCollection with embeddables differs quite a lot from the the other data types used in combination with @ElementCollection.
The primary concern is that embeddable properties are allowed to have null values.
This poses a couple of issues:

1) Since properties can be null, they have to be stored outside of the primary key (to e.g. support MSSQL) and some information has to be moved inside the primary key.
2) Since data can be stored outside of the composite-id, mappers needs an additional Map holding data outside of the composite-id and mappings XML needs adaptation.
3) This also affects the revision querying since the fields could be stored outside of the composite-id

A Set of Embeddables:

hibernate-envers\src\main\java\org\hibernate\envers\configuration\AuditEntitiesConfiguration.java

Added support for controlling the naming and type of the generated ordinal for Sets of Embeddables.

org.hibernate.envers.embeddable_set_ordinal_field_name defaulting to SETORDINAL
org.hibernate.envers.embeddable_set_ordinal_field_type defaulting to integer

hibernate-envers\src\main\java\org\hibernate\envers\configuration\metadata\AuditMetadataGenerator.java

Added an additional Element argument to addRevisionType to enable REVEND to be added outside of the primary key.
Additional argument primarily used from CollectionMetadataGenerator

hibernate-envers\src\main\java\org\hibernate\envers\configuration\metadata\CollectionMetadataGenerator.java

Added support for ComponentType using AuditedPropertiesReader, MiddleEmbeddableComponentMapper.

hibernate-envers\src\main\java\org\hibernate\envers\configuration\metadata\QueryGeneratorBuilder.java

Added boolean constructor argument (revisionTypeInId) to flag if the revisionType should be stored within the composite-id or as a field outside of the primary key.
The value is passed to the EntityQueryGenerator constructors.

hibernate-envers\src\main\java\org\hibernate\envers\configuration\metadata\reader\AuditedPropertiesHolder.java

Added an method for iterating of the property names.
Used by the CollectionMetadataGenerator to iterate over the properties created by the AuditedPropertiesReader.
This way field names, annotations etc are honored, e.g. @NotAudited (also available in tests).

hibernate-envers\src\main\java\org\hibernate\envers\configuration\metadata\reader\AuditedPropertiesReader.java

Changed ComponentPropertiesSource to be static public to be able to reuse the class in the CollectionMetadataGenerator.

hibernate-envers\src\main\java\org\hibernate\envers\entities\EntityInstantiator.java

Added getter for AuditConfiguration and AuditReaderImplementor.
Used by the newly added MiddleEmbeddableComponentMapper to be able to delegate mapping methods to the MultiPropertyMapper.

hibernate-envers\src\main\java\org\hibernate\envers\entities\mapper\CompositeMapperBuilder.java

Added Map getProperties() to enable access of nested properties.
Used by the MiddleEmbeddableComponentMapper to implement the addMiddleEqualToQuery.

hibernate-envers\src\main\java\org\hibernate\envers\entities\mapper\ExtendedPropertyMapper.java

Added getMapper(String propertyName) to access nested PropertyMappers.
Used by the ValidityAuditStrategy to update the previous revisions since the query now needs to consider data stored outside of the primary key (embeddables).

hibernate-envers\src\main\java\org\hibernate\envers\entities\mapper\PropertyMapper.java

Changed mapCollectionChanges to use the additional SessionImplementor argument.

hibernate-envers\src\main\java\org\hibernate\envers\entities\mapper\relation\CollectionPropertyMapper.java

Added needsDataComparision to allow the ValidityAuditStrategy to check if data should be compared on top of just primary key values.

hibernate-envers\src\main\java\org\hibernate\envers\entities\mapper\relation\AbstractCollectionMapper.java

Now implementing the CollectionPropertyMapper interface.
Changed mapCollectionChanges to use the additional SessionImplementor argument.
Added revisionTypeInId and ordinalInId as constructor arguments/fields to control where the revision type is stored and if an ordinal in the changeset needs to be generated.
Changed addCollectionChanges to add ordinal value if ordinalInId is enabled and added revisionType to data/id based on revisionTypeInId.
Added SessionImplementor and additional data-map to the mapToMapFromObject method to enable data addition outside of the primary key.

hibernate-envers\src\main\java\org\hibernate\envers\entities\mapper\relation\component\MiddleComponentMapper.java

Added SessionImplementor and additional data-map to the mapToMapFromObject method to enable data addition outside of the primary key.
Added rename the prefix1 and prefix2 to idPrefix1 and idPrefix2. Introduced prefix1 and prefix2 two again, but referring to the prefix to the data fields.
Added needsDataComparision to allow the ValidityAuditStrategy to check if data should be compared on top of just primary key values.

hibernate-envers\src\main\java\org\hibernate\envers\entities\mapper\relation\component\MiddleEmbeddableComponentMapper.java

MiddleComponentMapper implementation for mapping Embeddables.

hibernate-envers\src\main\java\org\hibernate\envers\entities\mapper\relation\query\OneEntityQueryGenerator.java
hibernate-envers\src\main\java\org\hibernate\envers\entities\mapper\relation\query\ThreeEntityQueryGenerator.java
hibernate-envers\src\main\java\org\hibernate\envers\entities\mapper\relation\query\TwoEntityOneAuditedQueryGenerator.java
hibernate-envers\src\main\java\org\hibernate\envers\entities\mapper\relation\query\TwoEntityQueryGenerator.java

Added revisionTypeInId as constructor argument to control where the revision type is stored

hibernate-envers\src\main\java\org\hibernate\envers\event\AuditEventListener.java

Changed mapCollectionChanges to use the additional SessionImplementor argument.

hibernate-envers\src\main\java\org\hibernate\envers\strategy\AuditStrategy.java

Added entityName, and propertyName arguments to the performCollectionChange.
Allows the ValidityAuditStrategy to retrieve the nested CollectionPropertyMapper and check if data needs to be compared on top of the primary key.

Added an additional alias1 to the addAssociationAtRevisionRestriction to pass the prefix to MiddleComponentMapper.addMiddleEqualToQuery

hibernate-envers\src\main\java\org\hibernate\envers\strategy\ValidityAuditStrategy.java

Compares the data as well as the primary key if needed, based on the CollectionPropertyMapper.needsDataComparision value.

hibernate-envers\src\main\java\org\hibernate\envers\synchronization\work\PersistentCollectionChangeWorkUnit.java

Changed mapCollectionChanges to use the additional SessionImplementor argument.

hibernate-envers\src\test\java\org\hibernate\envers\test\entities\collection\EmbeddableListEntity.java
hibernate-envers\src\test\java\org\hibernate\envers\test\entities\collection\EmbeddableMapEntity.java
hibernate-envers\src\test\java\org\hibernate\envers\test\entities\collection\EmbeddableSetEntity.java
hibernate-envers\src\test\java\org\hibernate\envers\test\entities\components\Component3.java
hibernate-envers\src\test\java\org\hibernate\envers\test\entities\components\Component4.java
hibernate-envers\src\test\java\org\hibernate\envers\test\integration\collection\EmbeddableList.java
hibernate-envers\src\test\java\org\hibernate\envers\test\integration\collection\EmbeddableMap.java
hibernate-envers\src\test\java\org\hibernate\envers\test\integration\collection\EmbeddableSet.java

Added tests