HHH-11748 - Fix relatedId queries against associated entities in entity identifier mappings.

This commit is contained in:
Chris Cranford 2017-05-15 17:11:28 -04:00
parent ac15d45da2
commit 843cce998f
3 changed files with 55 additions and 1 deletions

View File

@ -10,7 +10,6 @@ import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import org.dom4j.Element;
import org.hibernate.MappingException;
import org.hibernate.boot.registry.classloading.spi.ClassLoaderService;
import org.hibernate.boot.spi.MetadataImplementor;
@ -48,6 +47,9 @@ import org.hibernate.type.ManyToOneType;
import org.hibernate.type.OneToOneType;
import org.hibernate.type.TimestampType;
import org.hibernate.type.Type;
import org.dom4j.Element;
import org.jboss.logging.Logger;
/**
@ -743,6 +745,10 @@ public final class AuditMetadataGenerator {
// Mapping unjoined properties
final Element parent = xmlMappingData.getClassMapping();
// HHH-11748 - Generate a second pass for identifiers
// This is useful for situations where @Id point to @ManyToOne and @OneToOne associations.
idMetadataGenerator.generateSecondPass( entityName, pc );
addProperties(
parent,
pc.getUnjoinedPropertyIterator(),

View File

@ -16,6 +16,7 @@ import org.hibernate.envers.internal.entities.IdMappingData;
import org.hibernate.envers.internal.entities.PropertyData;
import org.hibernate.envers.internal.entities.mapper.SimpleMapperBuilder;
import org.hibernate.envers.internal.entities.mapper.id.EmbeddedIdMapper;
import org.hibernate.envers.internal.entities.mapper.id.IdMapper;
import org.hibernate.envers.internal.entities.mapper.id.MultipleIdMapper;
import org.hibernate.envers.internal.entities.mapper.id.SimpleIdMapperBuilder;
import org.hibernate.envers.internal.entities.mapper.id.SingleIdMapper;
@ -23,6 +24,7 @@ import org.hibernate.envers.internal.tools.ReflectionTools;
import org.hibernate.mapping.Component;
import org.hibernate.mapping.PersistentClass;
import org.hibernate.mapping.Property;
import org.hibernate.mapping.ToOne;
import org.hibernate.type.ManyToOneType;
import org.hibernate.type.Type;
@ -89,6 +91,41 @@ public final class IdMetadataGenerator {
return true;
}
public void generateSecondPass(String entityName, PersistentClass persistentClass) {
final Component identifierMapper = persistentClass.getIdentifierMapper();
final Property identifierProperty = persistentClass.getIdentifierProperty();
if ( identifierMapper != null ) {
generateSecondPass( entityName, identifierMapper );
}
else if ( identifierProperty != null && identifierProperty.isComposite() ) {
final Component component = (Component) identifierProperty.getValue();
generateSecondPass( entityName, component );
}
}
private void generateSecondPass(String entityName, Component component) {
Iterator properties = component.getPropertyIterator();
while ( properties.hasNext() ) {
final Property property = (Property) properties.next();
if ( property.getValue() instanceof ToOne ) {
final PropertyAuditingData propertyData = getIdPersistentPropertyAuditingData( property );
final String referencedEntityName = ( (ToOne) property.getValue() ).getReferencedEntityName();
final String prefix = mainGenerator.getVerEntCfg().getOriginalIdPropName() + "." + propertyData.getName();
final IdMapper relMapper = mainGenerator.getEntitiesConfigurations().get( referencedEntityName ).getIdMapper();
final IdMapper prefixedMapper = relMapper.prefixMappedProperties( prefix + "." );
mainGenerator.getEntitiesConfigurations().get( entityName ).addToOneRelation(
prefix,
referencedEntityName,
prefixedMapper,
true,
false
);
}
}
}
@SuppressWarnings({"unchecked"})
IdMappingData addId(PersistentClass pc, boolean audited) {
// Xml mapping which will be used for relations

View File

@ -89,6 +89,17 @@ public abstract class CriteriaTools {
if ( identifierPropertyNames.contains( propertyName ) ) {
propertyName = enversService.getAuditEntitiesConfiguration().getOriginalIdPropName() + "." + propertyName;
}
else if ( propertyName != null ) {
// if property starts with an identifier prefix ( e.g. embedded ids ), substitute with the originalId property
// because Envers performs replacement this automatically during the mapping.
for ( String identifierPropertyName : identifierPropertyNames ) {
if ( propertyName.startsWith( identifierPropertyName + "." ) ) {
propertyName = enversService.getAuditEntitiesConfiguration().getOriginalIdPropName() +
propertyName.substring( identifierPropertyName.length() );
break;
}
}
}
}
return propertyName;