From 103e5c658b7dac278fec57c51f597edb83ba7c06 Mon Sep 17 00:00:00 2001 From: Steve Ebersole Date: Tue, 14 Dec 2021 15:35:58 -0600 Subject: [PATCH] HHH-14977 - @Where is broken in 6.0 simple fix hooking in to the existing String based building. working on a version that uses the AST --- .../org/hibernate/internal/FilterHelper.java | 7 +- .../collection/OneToManyPersister.java | 9 +- .../mapping/where/DiscriminatorWhereTest.java | 134 ++++++++++++++++++ .../orm/test/mapping/where/package-info.java | 12 ++ 4 files changed, 159 insertions(+), 3 deletions(-) create mode 100644 hibernate-core/src/test/java/org/hibernate/orm/test/mapping/where/DiscriminatorWhereTest.java create mode 100644 hibernate-core/src/test/java/org/hibernate/orm/test/mapping/where/package-info.java diff --git a/hibernate-core/src/main/java/org/hibernate/internal/FilterHelper.java b/hibernate-core/src/main/java/org/hibernate/internal/FilterHelper.java index 3e689499e8..7bb0cd5aa7 100644 --- a/hibernate-core/src/main/java/org/hibernate/internal/FilterHelper.java +++ b/hibernate-core/src/main/java/org/hibernate/internal/FilterHelper.java @@ -16,6 +16,7 @@ import org.hibernate.Filter; import org.hibernate.MappingException; +import org.hibernate.engine.spi.FilterDefinition; import org.hibernate.engine.spi.LoadQueryInfluencers; import org.hibernate.engine.spi.SessionFactoryImplementor; import org.hibernate.internal.util.StringHelper; @@ -67,8 +68,9 @@ public FilterHelper(List filters, SessionFactoryImplementor filterNames[filterCount] = safeInterning( filter.getName() ); filterConditions[filterCount] = safeInterning( filter.getCondition() ); filterAliasTableMaps[filterCount] = filter.getAliasTableMap( factory ); - if ( ( filterAliasTableMaps[filterCount].isEmpty() || isTableFromPersistentClass( filterAliasTableMaps[filterCount] ) ) && filter - .useAutoAliasInjection() ) { + if ( ( filterAliasTableMaps[filterCount].isEmpty() + || isTableFromPersistentClass( filterAliasTableMaps[filterCount] ) ) + && filter.useAutoAliasInjection() ) { filterConditions[filterCount] = safeInterning( Template.renderWhereStringTemplate( filter.getCondition(), @@ -79,6 +81,7 @@ public FilterHelper(List filters, SessionFactoryImplementor ); filterAutoAliasFlags[filterCount] = true; } + filterConditions[filterCount] = safeInterning( StringHelper.replace( filterConditions[filterCount], diff --git a/hibernate-core/src/main/java/org/hibernate/persister/collection/OneToManyPersister.java b/hibernate-core/src/main/java/org/hibernate/persister/collection/OneToManyPersister.java index 314a7e27bd..8d6933522e 100644 --- a/hibernate-core/src/main/java/org/hibernate/persister/collection/OneToManyPersister.java +++ b/hibernate-core/src/main/java/org/hibernate/persister/collection/OneToManyPersister.java @@ -19,6 +19,7 @@ import org.hibernate.engine.jdbc.batch.internal.BasicBatchKey; import org.hibernate.engine.spi.SharedSessionContractImplementor; import org.hibernate.internal.FilterAliasGenerator; +import org.hibernate.internal.util.StringHelper; import org.hibernate.internal.util.collections.ArrayHelper; import org.hibernate.jdbc.Expectation; import org.hibernate.jdbc.Expectations; @@ -497,7 +498,13 @@ public String filterFragment(String alias) throws MappingException { protected String filterFragment(String alias, Set treatAsDeclarations) throws MappingException { String result = super.filterFragment( alias ); if ( getElementPersister() instanceof Joinable ) { - result += ( (Joinable) getElementPersister() ).oneToManyFilterFragment( alias, treatAsDeclarations ); + final String associationFilter = ( (Joinable) getElementPersister() ).oneToManyFilterFragment( alias, treatAsDeclarations ); + if ( StringHelper.isEmpty( result ) ) { + result = associationFilter; + } + else if ( StringHelper.isNotEmpty( associationFilter ) ) { + result += " and " + associationFilter; + } } return result; } diff --git a/hibernate-core/src/test/java/org/hibernate/orm/test/mapping/where/DiscriminatorWhereTest.java b/hibernate-core/src/test/java/org/hibernate/orm/test/mapping/where/DiscriminatorWhereTest.java new file mode 100644 index 0000000000..33ba6cb4ba --- /dev/null +++ b/hibernate-core/src/test/java/org/hibernate/orm/test/mapping/where/DiscriminatorWhereTest.java @@ -0,0 +1,134 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * License: GNU Lesser General Public License (LGPL), version 2.1 or later + * See the lgpl.txt file in the root directory or http://www.gnu.org/licenses/lgpl-2.1.html + */ +package org.hibernate.orm.test.mapping.where; + +import java.util.Set; + +import org.hibernate.annotations.Where; + +import org.hibernate.testing.orm.junit.DomainModel; +import org.hibernate.testing.orm.junit.JiraKey; +import org.hibernate.testing.orm.junit.SessionFactory; +import org.hibernate.testing.orm.junit.SessionFactoryScope; +import org.junit.jupiter.api.Test; + +import jakarta.persistence.DiscriminatorColumn; +import jakarta.persistence.DiscriminatorType; +import jakarta.persistence.DiscriminatorValue; +import jakarta.persistence.Entity; +import jakarta.persistence.GeneratedValue; +import jakarta.persistence.Id; +import jakarta.persistence.JoinColumn; +import jakarta.persistence.OneToMany; +import jakarta.persistence.Table; + +@DomainModel( annotatedClasses = { + DiscriminatorWhereTest.EntityA.class, + DiscriminatorWhereTest.EntityB.class, + DiscriminatorWhereTest.EntityC.class +}) +@SessionFactory +@JiraKey( "https://hibernate.atlassian.net/browse/HHH-14977" ) +public class DiscriminatorWhereTest { + @Test + public void testAddDiscriminatedEntityToCollectionWithWhere(SessionFactoryScope scope) { + // Initially save EntityA with an empty collection + final Integer id = scope.fromTransaction( (session) -> { + final EntityA entityA = new EntityA(); + entityA.setName( "a" ); + session.persist( entityA ); + return entityA.getId(); + } ); + + // Fetch EntityA and add a new EntityC to its collection. + // The collection is annotated with @Where("TYPE = 'C'") + scope.inTransaction( (session) -> { + final EntityA entityA = session.find( EntityA.class, id ); + final EntityC entityC = new EntityC(); + entityC.setName( "c" ); + + // `#add` triggers the error as it tries to fetch the Set + entityA.getAllMyC().add( entityC ); + + session.persist( entityC ); + // todo: this merge fails with a SQL exception + // Syntax error in SQL statement "SELECT A1_0.ALLC,A1_0.ID,A1_0.NAME FROM B_TAB A1_0 WHERE A1_0.ALLC=? AND (A1_0.TYPE = 'C') A1_0[*].TYPE='C' "; + session.merge( entityA ); + } ); + } + + @Entity(name = "EnttiyA") + @Table(name = "a_tab") + public static class EntityA { + @Id + @GeneratedValue + private Integer id; + private String name; + + @OneToMany + @JoinColumn(name = "allC") + @Where(clause = "TYPE = 'C'") + private Set allMyC; + + public Integer getId() { + return id; + } + + public void setId(Integer id) { + this.id = id; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public Set getAllMyC() { + return allMyC; + } + + public void setAllMyC(Set allMyC) { + this.allMyC = allMyC; + } + } + + @Entity(name = "EntityB") + @Table(name = "b_tab") + @DiscriminatorColumn(name = "type", discriminatorType = DiscriminatorType.STRING) + @DiscriminatorValue( value = "B") + public static class EntityB { + @Id + @GeneratedValue + private Integer id; + private String name; + + public Integer getId() { + return id; + } + + public void setId(Integer id) { + this.id = id; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + } + + @Entity(name = "EntityC") + @DiscriminatorValue(value = "C") + public static class EntityC extends EntityB { + + } +} diff --git a/hibernate-core/src/test/java/org/hibernate/orm/test/mapping/where/package-info.java b/hibernate-core/src/test/java/org/hibernate/orm/test/mapping/where/package-info.java new file mode 100644 index 0000000000..d7782e86a3 --- /dev/null +++ b/hibernate-core/src/test/java/org/hibernate/orm/test/mapping/where/package-info.java @@ -0,0 +1,12 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * License: GNU Lesser General Public License (LGPL), version 2.1 or later + * See the lgpl.txt file in the root directory or http://www.gnu.org/licenses/lgpl-2.1.html + */ + +/** + * Tests for {@link org.hibernate.annotations.Where} + */ +package org.hibernate.orm.test.mapping.where; +