HHH-11076 - Lazy collections ignore filters when allowLoadOutsideTransaction is true
Roll back fix since it got rejected due to some corner cases that are now added to ProxyPreservingFiltersOutsideInitialSessionTest
This commit is contained in:
parent
23326608f7
commit
8201c69103
|
@ -10,7 +10,6 @@ import java.io.Serializable;
|
|||
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;
|
||||
|
@ -18,7 +17,6 @@ import java.util.ListIterator;
|
|||
import java.util.Map;
|
||||
|
||||
import org.hibernate.AssertionFailure;
|
||||
import org.hibernate.Filter;
|
||||
import org.hibernate.FlushMode;
|
||||
import org.hibernate.HibernateException;
|
||||
import org.hibernate.LazyInitializationException;
|
||||
|
@ -75,7 +73,6 @@ public abstract class AbstractPersistentCollection implements Serializable, Pers
|
|||
|
||||
private String sessionFactoryUuid;
|
||||
private boolean allowLoadOutsideTransaction;
|
||||
private Map<String, Filter> enabledFilters;
|
||||
|
||||
/**
|
||||
* Not called by Hibernate, but used by non-JDK serialization,
|
||||
|
@ -86,7 +83,6 @@ public abstract class AbstractPersistentCollection implements Serializable, Pers
|
|||
|
||||
protected AbstractPersistentCollection(SharedSessionContractImplementor session) {
|
||||
this.session = session;
|
||||
enabledFilters = new HashMap<>( session.getLoadQueryInfluencers().getEnabledFilters() );
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -279,7 +275,6 @@ public abstract class AbstractPersistentCollection implements Serializable, Pers
|
|||
final SharedSessionContractImplementor session = (SharedSessionContractImplementor) sf.openSession();
|
||||
session.getPersistenceContext().setDefaultReadOnly( true );
|
||||
session.setFlushMode( FlushMode.MANUAL );
|
||||
session.getLoadQueryInfluencers().getEnabledFilters().putAll( enabledFilters );
|
||||
return session;
|
||||
}
|
||||
|
||||
|
|
|
@ -8,12 +8,16 @@ 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;
|
||||
|
||||
|
@ -22,6 +26,9 @@ import static org.junit.Assert.assertEquals;
|
|||
*/
|
||||
public class ProxyPreservingFiltersOutsideInitialSessionTest
|
||||
extends BaseEntityManagerFunctionalTestCase {
|
||||
|
||||
private static final Logger log = Logger.getLogger( ProxyPreservingFiltersOutsideInitialSessionTest.class );
|
||||
|
||||
@Override
|
||||
public Class[] getAnnotatedClasses() {
|
||||
return new Class[] {
|
||||
|
@ -38,6 +45,7 @@ public class ProxyPreservingFiltersOutsideInitialSessionTest
|
|||
}
|
||||
|
||||
@Test
|
||||
@FailureExpected( jiraKey = "HHH-11076", message = "Fix rejected, we need another approach to fix this issue!" )
|
||||
public void testPreserveFilters() {
|
||||
|
||||
doInJPA( this::entityManagerFactory, entityManager -> {
|
||||
|
@ -71,4 +79,179 @@ public class ProxyPreservingFiltersOutsideInitialSessionTest
|
|||
|
||||
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());
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue