HHH-12875 HHH-12882 : Class level where="..." clause hbm.xml mappings is not enforced on collections of that class; add parentheses when where clauses get combined in a conjunction (hbm and annotations)

HHH-12882 : correct assertions in ParentChildTest
This commit is contained in:
Gail Badner 2018-08-03 01:25:34 -07:00
parent cdf5e45514
commit 27937e5627
4 changed files with 79 additions and 44 deletions

View File

@ -1527,7 +1527,6 @@ public class ModelBinder {
binding.getSynchronizedTables().add( name ); binding.getSynchronizedTables().add( name );
} }
binding.setWhere( source.getWhere() );
binding.setLoaderName( source.getCustomLoaderName() ); binding.setLoaderName( source.getCustomLoaderName() );
if ( source.getCustomSqlInsert() != null ) { if ( source.getCustomSqlInsert() != null ) {
binding.setCustomSQLInsert( binding.setCustomSQLInsert(
@ -3448,9 +3447,15 @@ public class ModelBinder {
final PersistentClass referencedEntityBinding = mappingDocument.getMetadataCollector() final PersistentClass referencedEntityBinding = mappingDocument.getMetadataCollector()
.getEntityBinding( elementSource.getReferencedEntityName() ); .getEntityBinding( elementSource.getReferencedEntityName() );
collectionBinding.setWhere(
StringHelper.getNonEmptyOrConjunctionIfBothNonEmpty(
referencedEntityBinding.getWhere(),
getPluralAttributeSource().getWhere()
)
);
elementBinding.setReferencedEntityName( referencedEntityBinding.getEntityName() ); elementBinding.setReferencedEntityName( referencedEntityBinding.getEntityName() );
elementBinding.setAssociatedClass( referencedEntityBinding ); elementBinding.setAssociatedClass( referencedEntityBinding );
elementBinding.setIgnoreNotFound( elementSource.isIgnoreNotFound() ); elementBinding.setIgnoreNotFound( elementSource.isIgnoreNotFound() );
} }
else if ( getPluralAttributeSource().getElementSource() instanceof PluralAttributeElementSourceManyToMany ) { else if ( getPluralAttributeSource().getElementSource() instanceof PluralAttributeElementSourceManyToMany ) {
@ -3469,12 +3474,17 @@ public class ModelBinder {
new RelationalObjectBinder.ColumnNamingDelegate() { new RelationalObjectBinder.ColumnNamingDelegate() {
@Override @Override
public Identifier determineImplicitName(final LocalMetadataBuildingContext context) { public Identifier determineImplicitName(final LocalMetadataBuildingContext context) {
return context.getMetadataCollector().getDatabase().toIdentifier( Collection.DEFAULT_ELEMENT_COLUMN_NAME ); return context.getMetadataCollector()
.getDatabase()
.toIdentifier( Collection.DEFAULT_ELEMENT_COLUMN_NAME );
} }
} }
); );
elementBinding.setLazy( elementSource.getFetchCharacteristics().getFetchTiming() != FetchTiming.IMMEDIATE ); elementBinding.setLazy(
elementSource.getFetchCharacteristics()
.getFetchTiming() != FetchTiming.IMMEDIATE
);
elementBinding.setFetchMode( elementBinding.setFetchMode(
elementSource.getFetchCharacteristics().getFetchStyle() == FetchStyle.SELECT elementSource.getFetchCharacteristics().getFetchStyle() == FetchStyle.SELECT
? FetchMode.SELECT ? FetchMode.SELECT
@ -3494,20 +3504,16 @@ public class ModelBinder {
getCollectionBinding().setElement( elementBinding ); getCollectionBinding().setElement( elementBinding );
final StringBuilder whereBuffer = new StringBuilder(); final PersistentClass referencedEntityBinding = mappingDocument.getMetadataCollector().getEntityBinding(
final PersistentClass referencedEntityBinding = mappingDocument.getMetadataCollector() elementSource.getReferencedEntityName()
.getEntityBinding( elementSource.getReferencedEntityName() ); );
if ( StringHelper.isNotEmpty( referencedEntityBinding.getWhere() ) ) { getCollectionBinding().setWhere( getPluralAttributeSource().getWhere() );
whereBuffer.append( referencedEntityBinding.getWhere() ); getCollectionBinding().setManyToManyWhere(
} StringHelper.getNonEmptyOrConjunctionIfBothNonEmpty(
if ( StringHelper.isNotEmpty( elementSource.getWhere() ) ) { referencedEntityBinding.getWhere(),
if ( whereBuffer.length() > 0 ) { elementSource.getWhere()
whereBuffer.append( " and " ); )
} );
whereBuffer.append( elementSource.getWhere() );
}
getCollectionBinding().setManyToManyWhere( whereBuffer.toString() );
getCollectionBinding().setManyToManyOrdering( elementSource.getOrder() ); getCollectionBinding().setManyToManyOrdering( elementSource.getOrder() );
if ( !CollectionHelper.isEmpty( elementSource.getFilterSources() ) if ( !CollectionHelper.isEmpty( elementSource.getFilterSources() )

View File

@ -953,36 +953,27 @@ public abstract class CollectionBinder {
} }
} }
StringBuilder whereBuffer = new StringBuilder(); String whereOnClassClause = null;
if ( property.getElementClass() != null ) { if ( property.getElementClass() != null ) {
Where whereOnClass = property.getElementClass().getAnnotation( Where.class ); Where whereOnClass = property.getElementClass().getAnnotation( Where.class );
if ( whereOnClass != null ) { if ( whereOnClass != null ) {
String clause = whereOnClass.clause(); whereOnClassClause = whereOnClass.clause();
if ( StringHelper.isNotEmpty( clause ) ) {
whereBuffer.append( clause );
}
} }
} }
Where whereOnCollection = property.getAnnotation( Where.class ); Where whereOnCollection = property.getAnnotation( Where.class );
String whereOnCollectionClause = null;
if ( whereOnCollection != null ) { if ( whereOnCollection != null ) {
String clause = whereOnCollection.clause(); whereOnCollectionClause = whereOnCollection.clause();
if ( StringHelper.isNotEmpty( clause ) ) {
if ( whereBuffer.length() > 0 ) {
whereBuffer.append( ' ' );
whereBuffer.append( Junction.Nature.AND.getOperator() );
whereBuffer.append( ' ' );
}
whereBuffer.append( clause );
}
} }
if ( whereBuffer.length() > 0 ) { final String whereClause = StringHelper.getNonEmptyOrConjunctionIfBothNonEmpty(
String whereClause = whereBuffer.toString(); whereOnClassClause,
if ( hasAssociationTable ) { whereOnCollectionClause
collection.setManyToManyWhere( whereClause ); );
} if ( hasAssociationTable ) {
else { collection.setManyToManyWhere( whereClause );
collection.setWhere( whereClause ); }
} else {
collection.setWhere( whereClause );
} }
WhereJoinTable whereJoinTable = property.getAnnotation( WhereJoinTable.class ); WhereJoinTable whereJoinTable = property.getAnnotation( WhereJoinTable.class );

View File

@ -852,4 +852,38 @@ public final class StringHelper {
public interface Renderer<T> { public interface Renderer<T> {
String render(T value); String render(T value);
} }
/**
* @param firstExpression the first expression
* @param secondExpression the second expression
* @return if {@code firstExpression} and {@code secondExpression} are both non-empty,
* then "( " + {@code firstExpression} + " ) and ( " + {@code secondExpression} + " )" is returned;
* if {@code firstExpression} is non-empty and {@code secondExpression} is empty,
* then {@code firstExpression} is returned;
* if {@code firstExpression} is empty and {@code secondExpression} is non-empty,
* then {@code secondExpression} is returned;
* if both {@code firstExpression} and {@code secondExpression} are empty, then null is returned.
*/
public static String getNonEmptyOrConjunctionIfBothNonEmpty( String firstExpression, String secondExpression ) {
final boolean isFirstExpressionNonEmpty = StringHelper.isNotEmpty( firstExpression );
final boolean isSecondExpressionNonEmpty = StringHelper.isNotEmpty( secondExpression );
if ( isFirstExpressionNonEmpty && isSecondExpressionNonEmpty ) {
final StringBuilder buffer = new StringBuilder();
buffer.append( "( " )
.append( firstExpression )
.append( " ) and ( ")
.append( secondExpression )
.append( " )" );
return buffer.toString();
}
else if ( isFirstExpressionNonEmpty ) {
return firstExpression;
}
else if ( isSecondExpressionNonEmpty ) {
return secondExpression;
}
else {
return null;
}
}
} }

View File

@ -482,12 +482,16 @@ public class ParentChildTest extends LegacyTestCase {
assertTrue( s.createCriteria(Part.class).list().size()==1 ); //there is a where condition on Part mapping assertTrue( s.createCriteria(Part.class).list().size()==1 ); //there is a where condition on Part mapping
assertTrue( s.createCriteria(Part.class).add( Restrictions.eq( "id", p1.getId() ) ).list().size()==1 ); assertTrue( s.createCriteria(Part.class).add( Restrictions.eq( "id", p1.getId() ) ).list().size()==1 );
assertTrue( s.createQuery("from Part").list().size()==1 ); assertTrue( s.createQuery("from Part").list().size()==1 );
assertTrue( s.createQuery("from Baz baz join baz.parts").list().size()==2 ); // only Part entities that satisfy the where condition on Part mapping should be included in the collection
assertTrue( s.createQuery("from Baz baz join baz.parts").list().size()==1 );
baz = (Baz) s.createCriteria(Baz.class).uniqueResult(); baz = (Baz) s.createCriteria(Baz.class).uniqueResult();
assertTrue( s.createFilter( baz.getParts(), "" ).list().size()==2 ); // only Part entities that satisfy the where condition on Part mapping should be included in the collection
assertTrue( s.createFilter( baz.getParts(), "" ).list().size()==1 );
//assertTrue( baz.getParts().size()==1 ); //assertTrue( baz.getParts().size()==1 );
s.delete( s.get( Part.class, p1.getId() )); s.delete( s.get( Part.class, p1.getId() ) );
s.delete( s.get( Part.class, p2.getId() )); // p2.description does not satisfy the condition on Part mapping, so it's not possible to retrieve it
// using Session#get; instead just delete using a native query
s.createNativeQuery( "delete from Part where id = :id" ).setParameter( "id", p2.getId() ).executeUpdate();
s.delete(baz); s.delete(baz);
t.commit(); t.commit();
s.close(); s.close();