/* * 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.jpa.test.hibernateFilters; import java.util.Map; import org.hibernate.Hibernate; import org.hibernate.Session; import org.hibernate.cfg.AvailableSettings; import org.hibernate.jpa.test.BaseEntityManagerFunctionalTestCase; import org.hibernate.testing.FailureExpected; import org.junit.Test; import org.jboss.logging.Logger; import static org.hibernate.testing.transaction.TransactionUtil.doInJPA; import static org.junit.Assert.assertEquals; /** * @author Vlad Mihalcea */ public class ProxyPreservingFiltersOutsideInitialSessionTest extends BaseEntityManagerFunctionalTestCase { private static final Logger log = Logger.getLogger( ProxyPreservingFiltersOutsideInitialSessionTest.class ); @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 @FailureExpected( jiraKey = "HHH-11076", message = "Fix rejected, we need another approach to fix this issue!" ) 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()); } @Test public void testChangeFilterBeforeInitializeInSameSession() { 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 ); } ); doInJPA( this::entityManagerFactory, entityManager -> { entityManager.unwrap( Session.class ).enableFilter( "byRegion" ).setParameter( "region", "US" ); AccountGroup accountGroup = entityManager.find( AccountGroup.class, 1L ); // Change the filter entityManager.unwrap( Session.class ).enableFilter( "byRegion" ).setParameter( "region", "Europe" ); Hibernate.initialize( accountGroup.getAccounts() ); // will contain accounts with regionCode "Europe" assertEquals( 2, accountGroup.getAccounts().size() ); return accountGroup; } ); } @Test @FailureExpected( jiraKey = "HHH-11076", message = "Fix rejected, we need another approach to fix this issue!" ) public void testChangeFilterBeforeInitializeInTempSession() { 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" ); AccountGroup accountGroup = entityManager.find( AccountGroup.class, 1L ); // Change the filter. entityManager.unwrap( Session.class ).enableFilter( "byRegion" ).setParameter( "region", "Europe" ); return accountGroup; } ); log.info( "Initialize accounts collection" ); // What should group.getAccounts() contain? Should it be accounts with regionCode "Europe" // because that was the most recent filter used in the session? Hibernate.initialize( group.getAccounts() ); // The following will fail because the collection will only contain accounts with regionCode "US" assertEquals(2, group.getAccounts().size()); } @Test public void testMergeNoFilterThenInitializeTempSession() { 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 ); } ); final AccountGroup group = doInJPA( this::entityManagerFactory, entityManager -> { entityManager.unwrap( Session.class ).enableFilter( "byRegion" ).setParameter( "region", "US" ); return entityManager.find( AccountGroup.class, 1L ); } ); final AccountGroup mergedGroup = doInJPA( this::entityManagerFactory, entityManager -> { return entityManager.merge( group ); } ); // group.getAccounts() will be unfiltered because merge cleared AbstractCollectionPersister#enabledFilters Hibernate.initialize( mergedGroup.getAccounts() ); assertEquals(3, mergedGroup.getAccounts().size()); } @Test public void testSaveOrUpdateNoFilterThenInitializeTempSession() { 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 ); } ); final AccountGroup group = doInJPA( this::entityManagerFactory, entityManager -> { entityManager.unwrap( Session.class ).enableFilter( "byRegion" ).setParameter( "region", "US" ); return entityManager.find( AccountGroup.class, 1L ); } ); final AccountGroup savedGroup = doInJPA( this::entityManagerFactory, entityManager -> { // saveOrUpdate adds the PersistenceCollection to the session "as is" return (AccountGroup) entityManager.unwrap( Session.class ).merge( group ); } ); Hibernate.initialize( savedGroup.getAccounts() ); // group.getAccounts() should not be filtered. // the following fails because AbstractCollectionPersister#enabledFilters is still intact. assertEquals(3, savedGroup.getAccounts().size()); } }