Implement support for non-primary-key foreign keys

This commit is contained in:
Christian Beikov 2021-08-06 10:25:20 +02:00
parent 3ec8b27b2a
commit d3810b8f7a
6 changed files with 15 additions and 25 deletions

View File

@ -533,9 +533,11 @@ public void sortProperties() {
return;
}
final int[] originalPropertyOrder;
// We need to capture the original property order the source is a XML mapping
// We need to capture the original property order if this is an alternate unique key
// to be able to sort the other side of the foreign key accordingly
// and also if the source is a XML mapping
// because XML mappings might refer to this through the defined order
if ( getBuildingContext() instanceof MappingDocument ) {
if ( isAlternateUniqueKey() || getBuildingContext() instanceof MappingDocument ) {
final Object[] originalProperties = properties.toArray();
properties.sort( Comparator.comparing( Property::getName ) );
originalPropertyOrder = new int[originalProperties.length];

View File

@ -186,6 +186,8 @@ private EmbeddableMappingType(
if ( inverseMappingType.attributeMappings.isEmpty() ) {
return false;
}
// Reset the attribute mappings that were added in previous attempts
this.attributeMappings.clear();
int currentIndex = 0;
// We copy the attributes from the inverse mappings and replace the selection mappings
for ( AttributeMapping attributeMapping : inverseMappingType.attributeMappings ) {
@ -253,6 +255,9 @@ private boolean finishInitialization(
int attributeIndex = 0;
int columnPosition = 0;
// Reset the attribute mappings that were added in previous attempts
this.attributeMappings.clear();
final Iterator<Property> propertyIterator = bootDescriptor.getPropertyIterator();
while ( propertyIterator.hasNext() ) {
final Property bootPropertyDescriptor = propertyIterator.next();

View File

@ -19,7 +19,6 @@
import org.hibernate.MappingException;
import org.hibernate.NotYetImplementedFor6Exception;
import org.hibernate.SharedSessionContract;
import org.hibernate.boot.model.source.internal.hbm.MappingDocument;
import org.hibernate.collection.internal.StandardArraySemantics;
import org.hibernate.collection.internal.StandardBagSemantics;
import org.hibernate.collection.internal.StandardIdentifierBagSemantics;
@ -45,7 +44,6 @@
import org.hibernate.mapping.Property;
import org.hibernate.mapping.Resolvable;
import org.hibernate.mapping.Selectable;
import org.hibernate.mapping.SimpleValue;
import org.hibernate.mapping.Table;
import org.hibernate.mapping.ToOne;
import org.hibernate.mapping.Value;
@ -1032,12 +1030,7 @@ else if ( modelPart instanceof EmbeddableValuedModelPart ) {
fkTarget = referencedEntityDescriptor.getIdentifierMapping();
}
else {
// TODO: need some kind of virtual model part for this
// fkTarget = attributeMapping;//bootValueMapping.;
throw new NotYetImplementedFor6Exception(
"Support for non-pk foreign-keys not yet implemented: " +
bootProperty.getPersistentClass().getEntityName() + " -> " + bootProperty.getName()
);
fkTarget = referencedEntityDescriptor.findAttributeMapping( bootValueMapping.getReferencedPropertyName() );
}
if ( fkTarget instanceof BasicValuedModelPart ) {
@ -1198,27 +1191,19 @@ private static EmbeddedForeignKeyDescriptor buildEmbeddableForeignKeyDescriptor(
private static int[] getPropertyOrder(Value bootValueMapping, MappingModelCreationProcess creationProcess) {
final ComponentType componentType;
final boolean fromXml;
if ( bootValueMapping instanceof Collection ) {
final Collection collectionBootValueMapping = (Collection) bootValueMapping;
fromXml = collectionBootValueMapping.getBuildingContext() instanceof MappingDocument;
componentType = (ComponentType) collectionBootValueMapping.getKey().getType();
}
else {
if ( bootValueMapping instanceof OneToMany ) {
fromXml = ( (OneToMany) bootValueMapping ).getBuildingContext() instanceof MappingDocument;
}
else {
fromXml = ( (SimpleValue) bootValueMapping ).getBuildingContext() instanceof MappingDocument;
}
final EntityType entityType = (EntityType) bootValueMapping.getType();
final Type identifierOrUniqueKeyType = entityType.getIdentifierOrUniqueKeyType(
creationProcess.getCreationContext().getSessionFactory()
);
componentType = (ComponentType) identifierOrUniqueKeyType;
}
// If the value comes from XML, we need to consider the reordering
if ( fromXml ) {
// Consider the reordering if available
if ( componentType.getOriginalPropertyOrder() != null ) {
return componentType.getOriginalPropertyOrder();
}
// A value that came from the annotation model is already sorted appropriately

View File

@ -54,7 +54,9 @@ public void resolveKey(RowProcessingState rowProcessingState) {
final Object parentKey = parentAccess.getParentKey();
if ( parentKey != null ) {
// We can only use the parent key if the key descriptor uses the primary key of the owner i.e. refersToPrimaryKey
if ( parentKey != null && collectionAttributeMapping.getKeyDescriptor().getKeyPart().getNavigableRole().equals(
collectionAttributeMapping.findContainingEntityMapping().getIdentifierMapping().getNavigableRole() ) ) {
collectionKey = new CollectionKey(
collectionAttributeMapping.getCollectionDescriptor(),
parentKey

View File

@ -30,7 +30,6 @@
import org.hibernate.testing.FailureExpected;
import org.hibernate.testing.TestForIssue;
import org.hibernate.testing.orm.junit.Jpa;
import org.hibernate.testing.orm.junit.NotImplementedYet;
import org.hibernate.testing.orm.junit.EntityManagerFactoryScope;
import org.junit.jupiter.api.Test;
@ -45,7 +44,6 @@
MultiLevelCascadeCollectionEmbeddableTest.AnotherSubSubEntity.class,
MultiLevelCascadeCollectionEmbeddableTest.SubSubEntity.class
})
@NotImplementedYet(reason = "NotImplementedYetException thrown in the initialization method, by NativeNonSelectQueryPlanImpl.executeUpdate()")
public class MultiLevelCascadeCollectionEmbeddableTest {
private boolean initialized = false;

View File

@ -29,7 +29,6 @@
import org.hibernate.testing.FailureExpected;
import org.hibernate.testing.TestForIssue;
import org.hibernate.testing.orm.junit.Jpa;
import org.hibernate.testing.orm.junit.NotImplementedYet;
import org.hibernate.testing.orm.junit.EntityManagerFactoryScope;
import org.jboss.logging.Logger;
@ -46,7 +45,6 @@
MultiLevelCascadeCollectionIdClassTest.AnotherSubSubEntity.class,
MultiLevelCascadeCollectionIdClassTest.SubSubEntity.class
})
@NotImplementedYet(reason = "NotImplementedYetException thrown in the initialization method, by NativeNonSelectQueryPlanImpl.executeUpdate()")
public class MultiLevelCascadeCollectionIdClassTest {
private static final Logger log = Logger.getLogger( MultiLevelCascadeCollectionIdClassTest.class );