Skip to content

Commit

Permalink
HHH-12375 Fix for eager loading same named properties with conflictin…
Browse files Browse the repository at this point in the history
…g types
  • Loading branch information
beikov authored and dreab8 committed Mar 21, 2018
1 parent c56b6d7 commit c8217d9
Show file tree
Hide file tree
Showing 3 changed files with 126 additions and 14 deletions.
Expand Up @@ -152,9 +152,9 @@ protected void addPropertyPath(
String[] formulaTemplates,
Mapping factory) {
Type existingType = typesByPropertyPath.get( path );
if ( existingType != null ) {
if ( existingType != null || typesByPropertyPath.containsKey( path ) ) {
// If types match or the new type is not an association type, there is nothing for us to do
if ( type == existingType || !( type instanceof AssociationType ) ) {
if ( type == existingType || existingType == null || !( type instanceof AssociationType ) ) {
logDuplicateRegistration(
path,
existingType,
Expand All @@ -173,12 +173,12 @@ protected void addPropertyPath(
return;
}

Type newType;
Type newType = null;
MetadataImplementor metadata = (MetadataImplementor) factory;

if ( type instanceof AnyType ) {
// TODO: not sure how to handle any types
throw new UnsupportedOperationException( "Not yet implemented!" );
// TODO: not sure how to handle any types. For now we just return and let the first type dictate what type the property has...
return;
}
else if ( type instanceof CollectionType ) {
Collection thisCollection = metadata.getCollectionBinding( ( (CollectionType) existingType ).getRole() );
Expand All @@ -193,7 +193,7 @@ else if ( type instanceof CollectionType ) {
return;
}

// When we discover incompatible types, we register "null" as property type to signal that the property is not resolvable on the parent type
// When we discover incompatible types, we use "null" as property type to signal that the property is not resolvable on the parent type
newType = null;
if ( LOG.isTraceEnabled() ) {
LOG.tracev(
Expand All @@ -220,9 +220,6 @@ else if ( type instanceof EntityType ) {

newType = getCommonType( metadata, entityType1, entityType2 );
}
else {
throw new IllegalStateException( "Unexpected association type: " + type );
}

typesByPropertyPath.put( path, newType );
// Set everything to empty to signal action has to be taken!
Expand Down
Expand Up @@ -13,6 +13,7 @@
import org.hibernate.loader.PropertyPath;
import org.hibernate.persister.collection.CollectionPersister;
import org.hibernate.persister.collection.QueryableCollection;
import org.hibernate.persister.entity.AbstractEntityPersister;
import org.hibernate.persister.entity.EntityPersister;
import org.hibernate.type.Type;

Expand Down Expand Up @@ -90,8 +91,9 @@ public MetamodelGraphWalker(AssociationVisitationStrategy strategy, SessionFacto
private void visitEntityDefinition(EntityDefinition entityDefinition) {
strategy.startingEntity( entityDefinition );

AbstractEntityPersister persister = (AbstractEntityPersister) entityDefinition.getEntityPersister();
visitIdentifierDefinition( entityDefinition.getEntityKeyDefinition() );
visitAttributes( entityDefinition );
visitAttributes( entityDefinition, persister);

strategy.finishingEntity( entityDefinition );
}
Expand Down Expand Up @@ -122,17 +124,17 @@ private void visitIdentifierDefinition(EntityIdentifierDefinition identifierDefi
strategy.finishingEntityIdentifier( identifierDefinition );
}

private void visitAttributes(AttributeSource attributeSource) {
private void visitAttributes(AttributeSource attributeSource, AbstractEntityPersister sourcePersister) {
final Iterable<AttributeDefinition> attributeDefinitions = attributeSource.getAttributes();
if ( attributeDefinitions == null ) {
return;
}
for ( AttributeDefinition attributeDefinition : attributeDefinitions ) {
visitAttributeDefinition( attributeDefinition );
visitAttributeDefinition( attributeDefinition, sourcePersister);
}
}

private void visitAttributeDefinition(AttributeDefinition attributeDefinition) {
private void visitAttributeDefinition(AttributeDefinition attributeDefinition, AbstractEntityPersister sourcePersister) {
final PropertyPath subPath = currentPropertyPath.append( attributeDefinition.getName() );
log.debug( "Visiting attribute path : " + subPath.getFullPath() );

Expand All @@ -147,6 +149,14 @@ private void visitAttributeDefinition(AttributeDefinition attributeDefinition) {
// EARLY EXIT!!!
return;
}

if ( sourcePersister != null ) {
String[] columns = sourcePersister.toColumns(attributeDefinition.getName());
// Empty columns means that the attribute is not resolvable on this persister
if ( columns.length == 0 ) {
return;
}
}
}


Expand Down Expand Up @@ -196,7 +206,7 @@ private void visitAnyDefinition(AnyMappingDefinition anyDefinition) {
private void visitCompositeDefinition(CompositionDefinition compositionDefinition) {
strategy.startingComposite( compositionDefinition );

visitAttributes( compositionDefinition );
visitAttributes( compositionDefinition, null );

strategy.finishingComposite( compositionDefinition );
}
Expand Down
@@ -0,0 +1,105 @@
/*
* Hibernate, Relational Persistence for Idiomatic Java
*
* Copyright (c) 2014, Red Hat Inc. or third-party contributors as
* indicated by the @author tags or express copyright attribution
* statements applied by the authors. All third-party contributions are
* distributed under license by Red Hat Inc.
*
* This copyrighted material is made available to anyone wishing to use, modify,
* copy, or redistribute it subject to the terms and conditions of the GNU
* Lesser General Public License, as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
* for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this distribution; if not, write to:
* Free Software Foundation, Inc.
* 51 Franklin Street, Fifth Floor
* Boston, MA 02110-1301 USA
*/
package org.hibernate.test.inheritance.discriminator;

import org.hibernate.Session;
import org.hibernate.testing.TestForIssue;
import org.hibernate.testing.junit4.BaseCoreFunctionalTestCase;
import org.junit.Assert;
import org.junit.Test;

import javax.persistence.*;
import java.util.Set;

/**
* Test cases for joined inheritance with eager fetching.
*
* @author Christian Beikov
*/
public class JoinedInheritanceEagerTest extends BaseCoreFunctionalTestCase {

@Override
protected Class<?>[] getAnnotatedClasses() {
return new Class[] {
BaseEntity.class,
EntityA.class,
EntityB.class,
EntityC.class,
EntityD.class
};
}

@Test
@TestForIssue( jiraKey = "HHH-12375" )
public void joinUnrelatedCollectionOnBaseType() {
final Session s = openSession();
s.getTransaction().begin();

try {
s.createQuery("from BaseEntity b join b.attributes").list();
Assert.fail("Expected a resolution exception for property 'attributes'!");
} catch (IllegalArgumentException ex) {
Assert.assertTrue(ex.getMessage().contains("could not resolve property: attributes "));
} finally {
s.getTransaction().commit();
s.close();
}
}

@Entity(name = "BaseEntity")
@Inheritance(strategy = InheritanceType.JOINED)
public static class BaseEntity {
@Id
private long id;
}

@Entity(name = "EntityA")
public static class EntityA extends BaseEntity {
@OneToMany(fetch = FetchType.LAZY)
private Set<EntityC> attributes;
@ManyToOne(fetch = FetchType.EAGER)
private EntityC relation;
}

@Entity(name = "EntityB")
public static class EntityB extends BaseEntity {
@OneToMany(fetch = FetchType.LAZY)
private Set<EntityD> attributes;
@ManyToOne(fetch = FetchType.EAGER)
private EntityD relation;
}

@Entity(name = "EntityC")
public static class EntityC {
@Id
private long id;
}

@Entity(name = "EntityD")
public static class EntityD {
@Id
private long id;
}

}

0 comments on commit c8217d9

Please sign in to comment.