HHH-1570 - criteria-api: filtering by key-many-to-one causes invalid sql
This commit is contained in:
parent
4516dd45d6
commit
3e3b439e02
|
@ -71,31 +71,46 @@ public final class JoinHelper {
|
|||
* be used in the join
|
||||
*/
|
||||
public static String[] getAliasedLHSColumnNames(
|
||||
AssociationType type,
|
||||
String alias,
|
||||
int property,
|
||||
AssociationType associationType,
|
||||
String columnQualifier,
|
||||
int propertyIndex,
|
||||
int begin,
|
||||
OuterJoinLoadable lhsPersister,
|
||||
Mapping mapping
|
||||
) {
|
||||
if ( type.useLHSPrimaryKey() ) {
|
||||
return StringHelper.qualify( alias, lhsPersister.getIdentifierColumnNames() );
|
||||
Mapping mapping) {
|
||||
if ( associationType.useLHSPrimaryKey() ) {
|
||||
return StringHelper.qualify( columnQualifier, lhsPersister.getIdentifierColumnNames() );
|
||||
}
|
||||
else {
|
||||
String propertyName = type.getLHSPropertyName();
|
||||
if (propertyName==null) {
|
||||
return ArrayHelper.slice(
|
||||
lhsPersister.toColumns(alias, property),
|
||||
begin,
|
||||
type.getColumnSpan(mapping)
|
||||
);
|
||||
String propertyName = associationType.getLHSPropertyName();
|
||||
if ( propertyName == null ) {
|
||||
return ArrayHelper.slice(
|
||||
toColumns( lhsPersister, columnQualifier, propertyIndex ),
|
||||
begin,
|
||||
associationType.getColumnSpan( mapping )
|
||||
);
|
||||
}
|
||||
else {
|
||||
return ( (PropertyMapping) lhsPersister ).toColumns(alias, propertyName); //bad cast
|
||||
return ( (PropertyMapping) lhsPersister ).toColumns(columnQualifier, propertyName); //bad cast
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private static String[] toColumns(OuterJoinLoadable persister, String columnQualifier, int propertyIndex) {
|
||||
if ( propertyIndex >= 0 ) {
|
||||
return persister.toColumns( columnQualifier, propertyIndex );
|
||||
}
|
||||
else {
|
||||
final String[] cols = persister.getIdentifierColumnNames();
|
||||
final String[] result = new String[cols.length];
|
||||
|
||||
for ( int j = 0; j < cols.length; j++ ) {
|
||||
result[j] = StringHelper.qualify( columnQualifier, cols[j] );
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the columns of the owning entity which are to
|
||||
* be used in the join
|
||||
|
@ -116,8 +131,10 @@ public final class JoinHelper {
|
|||
if (propertyName==null) {
|
||||
//slice, to get the columns for this component
|
||||
//property
|
||||
return ArrayHelper.slice(
|
||||
lhsPersister.getSubclassPropertyColumnNames(property),
|
||||
return ArrayHelper.slice(
|
||||
property < 0
|
||||
? lhsPersister.getIdentifierColumnNames()
|
||||
: lhsPersister.getSubclassPropertyColumnNames(property),
|
||||
begin,
|
||||
type.getColumnSpan(mapping)
|
||||
);
|
||||
|
@ -131,11 +148,10 @@ public final class JoinHelper {
|
|||
}
|
||||
|
||||
public static String getLHSTableName(
|
||||
AssociationType type,
|
||||
int property,
|
||||
OuterJoinLoadable lhsPersister
|
||||
) {
|
||||
if ( type.useLHSPrimaryKey() ) {
|
||||
AssociationType type,
|
||||
int propertyIndex,
|
||||
OuterJoinLoadable lhsPersister) {
|
||||
if ( type.useLHSPrimaryKey() || propertyIndex < 0 ) {
|
||||
return lhsPersister.getTableName();
|
||||
}
|
||||
else {
|
||||
|
@ -144,7 +160,7 @@ public final class JoinHelper {
|
|||
//if there is no property-ref, assume the join
|
||||
//is to the subclass table (ie. the table of the
|
||||
//subclass that the association belongs to)
|
||||
return lhsPersister.getSubclassPropertyTableName(property);
|
||||
return lhsPersister.getSubclassPropertyTableName(propertyIndex);
|
||||
}
|
||||
else {
|
||||
//handle a property-ref
|
||||
|
@ -157,7 +173,7 @@ public final class JoinHelper {
|
|||
//assumes that the property-ref refers to a property of the subclass
|
||||
//table that the association belongs to (a reasonable guess)
|
||||
//TODO: fix this, add: OuterJoinLoadable.getSubclassPropertyTableName(String propertyName)
|
||||
propertyRefTable = lhsPersister.getSubclassPropertyTableName(property);
|
||||
propertyRefTable = lhsPersister.getSubclassPropertyTableName(propertyIndex);
|
||||
}
|
||||
return propertyRefTable;
|
||||
}
|
||||
|
|
|
@ -539,6 +539,34 @@ public class JoinWalker {
|
|||
);
|
||||
}
|
||||
}
|
||||
|
||||
// if the entity has a composite identifier, see if we need to handle
|
||||
// its sub-properties separately
|
||||
final Type idType = persister.getIdentifierType();
|
||||
if ( idType.isComponentType() ) {
|
||||
final CompositeType cidType = (CompositeType) idType;
|
||||
if ( cidType.isEmbedded() ) {
|
||||
// we have an embedded composite identifier. Most likely we need to process the composite
|
||||
// properties separately, although there is an edge case where the identifier is really
|
||||
// a simple identifier (single value) wrapped in a JPA @IdClass or even in the case of a
|
||||
// a simple identifier (single value) wrapped in a Hibernate composite type.
|
||||
//
|
||||
// We really do not have a built-in method to determine that. However, generally the
|
||||
// persister would report that there is single, physical identifier property which is
|
||||
// explicitly at odds with the notion of "embedded composite". So we use that for now
|
||||
if ( persister.getEntityMetamodel().getIdentifierProperty().isEmbedded() ) {
|
||||
walkComponentTree(
|
||||
cidType,
|
||||
-1,
|
||||
0,
|
||||
persister,
|
||||
alias,
|
||||
path.append( "" ),
|
||||
currentDepth
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -26,9 +26,12 @@ import java.util.List;
|
|||
|
||||
import org.junit.Test;
|
||||
|
||||
import org.hibernate.Criteria;
|
||||
import org.hibernate.Session;
|
||||
import org.hibernate.cfg.Configuration;
|
||||
import org.hibernate.cfg.Environment;
|
||||
import org.hibernate.criterion.Restrictions;
|
||||
|
||||
import org.hibernate.testing.junit4.BaseCoreFunctionalTestCase;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
|
@ -48,6 +51,18 @@ public class KeyManyToOneTest extends BaseCoreFunctionalTestCase {
|
|||
cfg.setProperty( Environment.GENERATE_STATISTICS, "true" );
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testCriteriaRestrictionOnKeyManyToOne() {
|
||||
Session s = openSession();
|
||||
s.beginTransaction();
|
||||
s.createQuery( "from Order o where o.customer.name = 'Acme'" ).list();
|
||||
Criteria criteria = s.createCriteria( Order.class );
|
||||
criteria.createCriteria( "customer" ).add( Restrictions.eq( "name", "Acme" ) );
|
||||
criteria.list();
|
||||
s.getTransaction().commit();
|
||||
s.close();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSaveCascadedToKeyManyToOne() {
|
||||
// test cascading a save to an association with a key-many-to-one which refers to a
|
||||
|
|
Loading…
Reference in New Issue