HHH-13084 HHH-13114 : Bugs querying entity with non-ID property named 'id'

HHH-13084 HHH-13114 : Query 'select count(h) from Human h' fails if a subclass has a non-Id property named 'id'

HHH-13084 HHH-13114 : Update hibernate-core/src/main/java/org/hibernate/hql/internal/ast/tree/FromElement.java

Co-Authored-By: dreab8 <dreborier@gmail.com>

HHH-13084 HHH-13114 - Fix FromElementType method name

HHH-13084 HHH-13114 : Correct generated column names
This commit is contained in:
Gail Badner 2018-11-06 15:02:02 -08:00
parent 346b3c7f3e
commit 7316307d0e
6 changed files with 56 additions and 91 deletions

View File

@ -339,12 +339,18 @@ public class FromElement extends HqlSqlWalkerNode implements DisplayableNode, Pa
throw new IllegalStateException( "No table alias for node " + this );
}
final String propertyName = getIdentifierPropertyName();
return toColumns(
table, propertyName,
getWalker().getStatementType() == HqlSqlTokenTypes.SELECT
);
final String[] propertyNames = getIdentifierPropertyNames();
List<String> columns = new ArrayList<>();
for ( int i = 0; i < propertyNames.length; i++ ) {
String[] propertyNameColumns = toColumns(
table, propertyNames[i],
getWalker().getStatementType() == HqlSqlTokenTypes.SELECT
);
for ( int j = 0; j < propertyNameColumns.length; j++ ) {
columns.add( propertyNameColumns[j] );
}
}
return columns.toArray( new String[columns.size()] );
}
public void setCollectionJoin(boolean collectionJoin) {
@ -525,8 +531,8 @@ public class FromElement extends HqlSqlWalkerNode implements DisplayableNode, Pa
return elementType.getCollectionPropertyReference( propertyName );
}
public String getIdentifierPropertyName() {
return elementType.getIdentifierPropertyName();
public String[] getIdentifierPropertyNames() {
return elementType.getIdentifierPropertyNames();
}
public void setFetch(boolean fetch) {

View File

@ -14,17 +14,14 @@ import java.util.Set;
import org.hibernate.MappingException;
import org.hibernate.QueryException;
import org.hibernate.engine.internal.JoinSequence;
import org.hibernate.engine.spi.SessionFactoryImplementor;
import org.hibernate.hql.internal.CollectionProperties;
import org.hibernate.hql.internal.CollectionSubqueryFactory;
import org.hibernate.hql.internal.NameGenerator;
import org.hibernate.hql.internal.antlr.HqlSqlTokenTypes;
import org.hibernate.hql.internal.ast.HqlSqlWalker;
import org.hibernate.hql.internal.ast.util.SessionFactoryHelper;
import org.hibernate.internal.CoreLogging;
import org.hibernate.internal.CoreMessageLogger;
import org.hibernate.internal.log.DeprecationLogger;
import org.hibernate.internal.util.collections.ArrayHelper;
import org.hibernate.loader.PropertyPath;
import org.hibernate.param.ParameterSpecification;
import org.hibernate.persister.collection.CollectionPropertyMapping;
import org.hibernate.persister.collection.CollectionPropertyNames;
@ -33,6 +30,8 @@ import org.hibernate.persister.entity.EntityPersister;
import org.hibernate.persister.entity.Joinable;
import org.hibernate.persister.entity.PropertyMapping;
import org.hibernate.persister.entity.Queryable;
import org.hibernate.tuple.IdentifierProperty;
import org.hibernate.type.EmbeddedComponentType;
import org.hibernate.type.EntityType;
import org.hibernate.type.Type;
@ -130,18 +129,22 @@ class FromElementType {
String renderScalarIdentifierSelect(int i) {
checkInitialized();
final String idPropertyName = getIdentifierPropertyName();
String[] cols = getPropertyMapping( idPropertyName ).toColumns( getTableAlias(), idPropertyName );
final String[] idPropertyName = getIdentifierPropertyNames();
StringBuilder buf = new StringBuilder();
// For property references generate <tablealias>.<columnname> as <projectionalias>
for ( int j = 0; j < cols.length; j++ ) {
String column = cols[j];
if ( j > 0 ) {
buf.append( ", " );
int counter = 0;
for ( int j = 0; j < idPropertyName.length; j++ ) {
String propertyName = idPropertyName[j];
String[] toColumns = getPropertyMapping( propertyName ).toColumns( getTableAlias(), propertyName );
for ( int h = 0; h < toColumns.length; h++, counter++ ) {
String column = toColumns[h];
if ( j + h > 0 ) {
buf.append( ", " );
}
buf.append( column ).append( " as " ).append( NameGenerator.scalarName( i, counter ) );
}
buf.append( column ).append( " as " ).append( NameGenerator.scalarName( i, j ) );
}
LOG.debug( "Rendered scalar ID select column(s): " + buf );
return buf.toString();
}
@ -682,13 +685,25 @@ class FromElementType {
}
}
public String getIdentifierPropertyName() {
if ( getEntityPersister() != null && getEntityPersister().getEntityMetamodel() != null
&& getEntityPersister().getEntityMetamodel().hasNonIdentifierPropertyNamedId() ) {
return getEntityPersister().getIdentifierPropertyName();
}
else {
return EntityPersister.ENTITY_ID;
public String[] getIdentifierPropertyNames() {
if ( getEntityPersister() != null ) {
String identifierPropertyName = getEntityPersister().getIdentifierPropertyName();
if ( identifierPropertyName != null ) {
return new String[] { identifierPropertyName };
}
else {
final IdentifierProperty identifierProperty = getEntityPersister().getEntityMetamodel()
.getIdentifierProperty();
if ( identifierProperty.hasIdentifierMapper() && !identifierProperty.isEmbedded() ) {
return new String[] { PropertyPath.IDENTIFIER_MAPPER_PROPERTY };
}
else {
if ( EmbeddedComponentType.class.isInstance( identifierProperty.getType() ) ) {
return ( (EmbeddedComponentType) identifierProperty.getType() ).getPropertyNames();
}
}
}
}
return new String[] { EntityPersister.ENTITY_ID };
}
}

View File

@ -2300,7 +2300,7 @@ public abstract class AbstractEntityPersister
new String[] {idColumnNames[i]}
);
}
// if (hasIdentifierProperty() && !ENTITY_ID.equals( getIdentifierPropertyName() ) ) {
// if (hasIdentifierProperty() && !ENTITY_ID.equals( getIdentifierPropertyNames() ) ) {
if ( hasIdentifierProperty() ) {
subclassPropertyAliases.put(
getIdentifierPropertyName() + "." + idPropertyNames[i],

View File

@ -81,57 +81,4 @@ public class PropertyNamedIdInNonJpaCompositeIdTest extends BaseCoreFunctionalTe
this.id = id;
}
}
public static class PersonId implements Serializable {
private String name;
private Integer id;
public PersonId() {
}
public PersonId(String name, int id) {
setName( name );
setId( id );
}
public String getName() {
return name;
}
public Integer getId() {
return id;
}
public void setName(String name) {
this.name = name;
}
public void setId(Integer id) {
this.id = id;
}
@Override
public boolean equals(Object o) {
if ( this == o ) {
return true;
}
if ( o == null || getClass() != o.getClass() ) {
return false;
}
PersonId personId = (PersonId) o;
if ( id != personId.id ) {
return false;
}
return name.equals( personId.name );
}
@Override
public int hashCode() {
int result = name.hashCode();
result = 31 * result + id;
return result;
}
}
}

View File

@ -43,8 +43,8 @@ public class PropertyNamedIdOutOfIdClassTest extends BaseCoreFunctionalTestCase
@TestForIssue(jiraKey = "HHH-13084")
public void testHql() {
doInHibernate( this::sessionFactory, session -> {
// assertEquals( 1, session.createQuery( "from Person p where p.id is null", Person.class ).list().size() );
// assertEquals( 2, session.createQuery( "from Person p where p.id is not null", Person.class ).list().size() );
assertEquals( 1, session.createQuery( "from Person p where p.id is null", Person.class ).list().size() );
assertEquals( 2, session.createQuery( "from Person p where p.id is not null", Person.class ).list().size() );
assertEquals( 3L, session.createQuery( "select count( p ) from Person p" ).uniqueResult() );
} );
}

View File

@ -16,6 +16,7 @@ import org.junit.Before;
import org.junit.Test;
import static org.hibernate.testing.transaction.TransactionUtil.doInHibernate;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.fail;
/**
@ -39,13 +40,9 @@ public class PropertyNamedIdOutOfNonJpaCompositeIdTest extends BaseCoreFunctiona
@Test
public void testHql() {
doInHibernate( this::sessionFactory, session -> {
try {
session.createQuery( "from Person p where p.id is null", Person.class ).list();
fail( "should have thrown UnsupportedOperationException" );
}
catch (UnsupportedOperationException ex) {
//expected
}
assertEquals( 1, session.createQuery( "from Person p where p.id = 1", Person.class ).list().size() );
assertEquals( 3L, session.createQuery( "select count( p ) from Person p" ).uniqueResult() );
} );
}