From ae40de125ded9e9570cbf7d92100c920b2d8429d Mon Sep 17 00:00:00 2001 From: Giovanni Lovato Date: Thu, 1 Sep 2016 14:51:57 +0200 Subject: [PATCH] HHH-11076 - Lazy collections ignore filters when allowLoadOutsideTransaction is true --- .../AbstractPersistentCollection.java | 9 ++- .../test/hibernateFilters/AccountGroup.java | 47 ++++++++++++ ...rvingFiltersOutsideInitialSessionTest.java | 74 +++++++++++++++++++ 3 files changed, 127 insertions(+), 3 deletions(-) create mode 100644 hibernate-core/src/test/java/org/hibernate/jpa/test/hibernateFilters/AccountGroup.java create mode 100644 hibernate-core/src/test/java/org/hibernate/jpa/test/hibernateFilters/ProxyPreservingFiltersOutsideInitialSessionTest.java diff --git a/hibernate-core/src/main/java/org/hibernate/collection/internal/AbstractPersistentCollection.java b/hibernate-core/src/main/java/org/hibernate/collection/internal/AbstractPersistentCollection.java index e03f9f97f529..4c474af95681 100644 --- a/hibernate-core/src/main/java/org/hibernate/collection/internal/AbstractPersistentCollection.java +++ b/hibernate-core/src/main/java/org/hibernate/collection/internal/AbstractPersistentCollection.java @@ -10,6 +10,7 @@ import java.util.ArrayList; import java.util.Collection; import java.util.Collections; +import java.util.HashMap; import java.util.HashSet; import java.util.Iterator; import java.util.List; @@ -17,6 +18,7 @@ import java.util.Map; import org.hibernate.AssertionFailure; +import org.hibernate.Filter; import org.hibernate.FlushMode; import org.hibernate.HibernateException; import org.hibernate.LazyInitializationException; @@ -73,6 +75,7 @@ public abstract class AbstractPersistentCollection implements Serializable, Pers private String sessionFactoryUuid; private boolean allowLoadOutsideTransaction; + private Map enabledFilters; /** * Not called by Hibernate, but used by non-JDK serialization, @@ -83,6 +86,7 @@ public AbstractPersistentCollection() { protected AbstractPersistentCollection(SharedSessionContractImplementor session) { this.session = session; + enabledFilters = new HashMap<>( session.getLoadQueryInfluencers().getEnabledFilters() ); } @Override @@ -218,7 +222,6 @@ else if ( !session.isConnected() ) { } } - SharedSessionContractImplementor originalSession = null; boolean isJTA = false; @@ -227,9 +230,8 @@ else if ( !session.isConnected() ) { originalSession = session; session = tempSession; - isJTA = session.getTransactionCoordinator().getTransactionCoordinatorBuilder().isJta(); - + if ( !isJTA ) { // Explicitly handle the transactions only if we're not in // a JTA environment. A lazy loading temporary session can @@ -277,6 +279,7 @@ private SharedSessionContractImplementor openTemporarySessionForLoading() { final SharedSessionContractImplementor session = (SharedSessionContractImplementor) sf.openSession(); session.getPersistenceContext().setDefaultReadOnly( true ); session.setFlushMode( FlushMode.MANUAL ); + session.getLoadQueryInfluencers().getEnabledFilters().putAll( enabledFilters ); return session; } diff --git a/hibernate-core/src/test/java/org/hibernate/jpa/test/hibernateFilters/AccountGroup.java b/hibernate-core/src/test/java/org/hibernate/jpa/test/hibernateFilters/AccountGroup.java new file mode 100644 index 000000000000..f9beb467c5c2 --- /dev/null +++ b/hibernate-core/src/test/java/org/hibernate/jpa/test/hibernateFilters/AccountGroup.java @@ -0,0 +1,47 @@ +/* + * 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 . + */ +package org.hibernate.jpa.test.hibernateFilters; + +import java.util.ArrayList; +import java.util.List; +import javax.persistence.Entity; +import javax.persistence.Id; +import javax.persistence.JoinColumn; +import javax.persistence.OneToMany; + +import org.hibernate.annotations.Filter; + +/** + * @author Vlad Mihalcea + */ +@Entity +public class AccountGroup { + + @Id + private Long id; + + @OneToMany + @JoinColumn(name = "group_id") + @Filter( name = "byRegion", condition = "region_cd = :region" ) + private List accounts = new ArrayList<>(); + + public Long getId() { + return id; + } + + public void setId(Long id) { + this.id = id; + } + + public List getAccounts() { + return accounts; + } + + public void setAccounts(List accounts) { + this.accounts = accounts; + } +} diff --git a/hibernate-core/src/test/java/org/hibernate/jpa/test/hibernateFilters/ProxyPreservingFiltersOutsideInitialSessionTest.java b/hibernate-core/src/test/java/org/hibernate/jpa/test/hibernateFilters/ProxyPreservingFiltersOutsideInitialSessionTest.java new file mode 100644 index 000000000000..2efa6ea70930 --- /dev/null +++ b/hibernate-core/src/test/java/org/hibernate/jpa/test/hibernateFilters/ProxyPreservingFiltersOutsideInitialSessionTest.java @@ -0,0 +1,74 @@ +/* + * 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 . + */ +package org.hibernate.jpa.test.hibernateFilters; + +import java.util.Map; + +import org.hibernate.Session; +import org.hibernate.cfg.AvailableSettings; +import org.hibernate.jpa.test.BaseEntityManagerFunctionalTestCase; + +import org.junit.Test; + +import static org.hibernate.testing.transaction.TransactionUtil.doInJPA; +import static org.junit.Assert.assertEquals; + +/** + * @author Vlad Mihalcea + */ +public class ProxyPreservingFiltersOutsideInitialSessionTest + extends BaseEntityManagerFunctionalTestCase { + @Override + public Class[] getAnnotatedClasses() { + return new Class[] { + AccountGroup.class, + Account.class + }; + } + + @Override + protected Map buildSettings() { + Map settings = super.buildSettings(); + settings.put( AvailableSettings.ENABLE_LAZY_LOAD_NO_TRANS, "true" ); + return settings; + } + + @Test + public void testPreserveFilters() { + + doInJPA( this::entityManagerFactory, entityManager -> { + AccountGroup accountGroup = new AccountGroup(); + accountGroup.setId( 1L ); + entityManager.persist( accountGroup ); + + Account account = new Account(); + account.setName( "A1" ); + account.setRegionCode( "Europe" ); + entityManager.persist( account ); + accountGroup.getAccounts().add( account ); + + account = new Account(); + account.setName( "A2" ); + account.setRegionCode( "Europe" ); + entityManager.persist( account ); + accountGroup.getAccounts().add( account ); + + account = new Account(); + account.setName( "A3" ); + account.setRegionCode( "US" ); + entityManager.persist( account ); + accountGroup.getAccounts().add( account ); + } ); + + AccountGroup group = doInJPA( this::entityManagerFactory, entityManager -> { + entityManager.unwrap( Session.class ).enableFilter( "byRegion" ).setParameter( "region", "US" ); + return entityManager.find( AccountGroup.class, 1L ); + } ); + + assertEquals(1, group.getAccounts().size()); + } +}