HHH-10202 : Delay resolving TypeScopeImpl#factory after deserialization until resolveFactory() is called.
This commit is contained in:
parent
e59781487a
commit
c835cf11ec
|
@ -12,9 +12,11 @@ import java.util.Properties;
|
||||||
|
|
||||||
import org.hibernate.HibernateException;
|
import org.hibernate.HibernateException;
|
||||||
import org.hibernate.MappingException;
|
import org.hibernate.MappingException;
|
||||||
|
import org.hibernate.boot.cfgxml.spi.CfgXmlAccessService;
|
||||||
import org.hibernate.classic.Lifecycle;
|
import org.hibernate.classic.Lifecycle;
|
||||||
import org.hibernate.engine.spi.SessionFactoryImplementor;
|
import org.hibernate.engine.spi.SessionFactoryImplementor;
|
||||||
import org.hibernate.internal.CoreMessageLogger;
|
import org.hibernate.internal.CoreMessageLogger;
|
||||||
|
import org.hibernate.internal.SessionFactoryRegistry;
|
||||||
import org.hibernate.internal.util.ReflectHelper;
|
import org.hibernate.internal.util.ReflectHelper;
|
||||||
import org.hibernate.tuple.component.ComponentMetamodel;
|
import org.hibernate.tuple.component.ComponentMetamodel;
|
||||||
import org.hibernate.usertype.CompositeUserType;
|
import org.hibernate.usertype.CompositeUserType;
|
||||||
|
@ -44,7 +46,9 @@ public final class TypeFactory implements Serializable {
|
||||||
}
|
}
|
||||||
|
|
||||||
private static class TypeScopeImpl implements TypeFactory.TypeScope {
|
private static class TypeScopeImpl implements TypeFactory.TypeScope {
|
||||||
private SessionFactoryImplementor factory;
|
private transient SessionFactoryImplementor factory;
|
||||||
|
private String sessionFactoryName;
|
||||||
|
private String sessionFactoryUuid;
|
||||||
|
|
||||||
public void injectSessionFactory(SessionFactoryImplementor factory) {
|
public void injectSessionFactory(SessionFactoryImplementor factory) {
|
||||||
if ( this.factory != null ) {
|
if ( this.factory != null ) {
|
||||||
|
@ -52,13 +56,31 @@ public final class TypeFactory implements Serializable {
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
LOG.tracev( "Scoping types to session factory {0}", factory );
|
LOG.tracev( "Scoping types to session factory {0}", factory );
|
||||||
|
sessionFactoryUuid = factory.getUuid();
|
||||||
|
String sfName = factory.getSettings().getSessionFactoryName();
|
||||||
|
if ( sfName == null ) {
|
||||||
|
final CfgXmlAccessService cfgXmlAccessService = factory.getServiceRegistry()
|
||||||
|
.getService( CfgXmlAccessService.class );
|
||||||
|
if ( cfgXmlAccessService.getAggregatedConfig() != null ) {
|
||||||
|
sfName = cfgXmlAccessService.getAggregatedConfig().getSessionFactoryName();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
sessionFactoryName = sfName;
|
||||||
}
|
}
|
||||||
this.factory = factory;
|
this.factory = factory;
|
||||||
}
|
}
|
||||||
|
|
||||||
public SessionFactoryImplementor resolveFactory() {
|
public SessionFactoryImplementor resolveFactory() {
|
||||||
if ( factory == null ) {
|
if ( factory == null ) {
|
||||||
throw new HibernateException( "SessionFactory for type scoping not yet known" );
|
factory = (SessionFactoryImplementor) SessionFactoryRegistry.INSTANCE.findSessionFactory(
|
||||||
|
sessionFactoryUuid,
|
||||||
|
sessionFactoryName
|
||||||
|
);
|
||||||
|
if ( factory == null ) {
|
||||||
|
throw new HibernateException(
|
||||||
|
"Could not find a SessionFactory [uuid=" + sessionFactoryUuid + ",name=" + sessionFactoryName + "]"
|
||||||
|
);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return factory;
|
return factory;
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,189 @@
|
||||||
|
/*
|
||||||
|
* 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.test.serialization;
|
||||||
|
|
||||||
|
import org.junit.Test;
|
||||||
|
|
||||||
|
import org.hibernate.HibernateException;
|
||||||
|
import org.hibernate.cfg.AvailableSettings;
|
||||||
|
import org.hibernate.cfg.Configuration;
|
||||||
|
import org.hibernate.engine.spi.SessionFactoryImplementor;
|
||||||
|
import org.hibernate.internal.SessionFactoryRegistry;
|
||||||
|
import org.hibernate.internal.util.SerializationHelper;
|
||||||
|
import org.hibernate.testing.junit4.BaseUnitTestCase;
|
||||||
|
import org.hibernate.type.TypeFactory;
|
||||||
|
|
||||||
|
import static org.junit.Assert.assertFalse;
|
||||||
|
import static org.junit.Assert.assertNull;
|
||||||
|
import static org.junit.Assert.assertSame;
|
||||||
|
import static org.junit.Assert.fail;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Gail Badner
|
||||||
|
*/
|
||||||
|
public class TypeFactorySerializationTest extends BaseUnitTestCase {
|
||||||
|
private static String NAME = "test name";
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testWithSameRegisteredSessionFactory() throws Exception {
|
||||||
|
Configuration cfg = new Configuration()
|
||||||
|
.setProperty( AvailableSettings.SESSION_FACTORY_NAME, NAME )
|
||||||
|
.setProperty( AvailableSettings.SESSION_FACTORY_NAME_IS_JNDI, "false" ); // default is true
|
||||||
|
SessionFactoryImplementor factory = (SessionFactoryImplementor) cfg.buildSessionFactory();
|
||||||
|
|
||||||
|
// Session factory is registered.
|
||||||
|
assertSame( factory, SessionFactoryRegistry.INSTANCE.getNamedSessionFactory( NAME ) );
|
||||||
|
|
||||||
|
TypeFactory typeFactory = factory.getTypeResolver().getTypeFactory();
|
||||||
|
byte[] typeFactoryBytes = SerializationHelper.serialize( typeFactory );
|
||||||
|
typeFactory = (TypeFactory) SerializationHelper.deserialize( typeFactoryBytes );
|
||||||
|
|
||||||
|
assertSame( factory, typeFactory.resolveSessionFactory() );
|
||||||
|
factory.close();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testUnregisterSerializeRegisterSameSessionFactory() throws Exception {
|
||||||
|
Configuration cfg = new Configuration()
|
||||||
|
.setProperty( AvailableSettings.SESSION_FACTORY_NAME, NAME )
|
||||||
|
.setProperty( AvailableSettings.SESSION_FACTORY_NAME_IS_JNDI, "false" ); // default is true
|
||||||
|
SessionFactoryImplementor factory = (SessionFactoryImplementor) cfg.buildSessionFactory();
|
||||||
|
assertSame( factory, SessionFactoryRegistry.INSTANCE.getNamedSessionFactory( NAME ) );
|
||||||
|
|
||||||
|
// Remove the session factory from the registry
|
||||||
|
SessionFactoryRegistry.INSTANCE.removeSessionFactory( factory.getUuid(), NAME, false, null );
|
||||||
|
assertNull( SessionFactoryRegistry.INSTANCE.findSessionFactory( factory.getUuid(), NAME ) );
|
||||||
|
|
||||||
|
TypeFactory typeFactory = factory.getTypeResolver().getTypeFactory();
|
||||||
|
byte[] typeFactoryBytes = SerializationHelper.serialize( typeFactory );
|
||||||
|
typeFactory = (TypeFactory) SerializationHelper.deserialize( typeFactoryBytes );
|
||||||
|
|
||||||
|
try {
|
||||||
|
typeFactory.resolveSessionFactory();
|
||||||
|
fail( "should have failed with HibernateException because session factory is not registered." );
|
||||||
|
}
|
||||||
|
catch ( HibernateException ex ) {
|
||||||
|
// expected because the session factory is not registered.
|
||||||
|
}
|
||||||
|
|
||||||
|
// Re-register the same session factory.
|
||||||
|
SessionFactoryRegistry.INSTANCE.addSessionFactory( factory.getUuid(), NAME, false, factory, null );
|
||||||
|
|
||||||
|
// Session factory resolved from typeFactory should be the new session factory
|
||||||
|
// (because it is resolved from SessionFactoryRegistry.INSTANCE)
|
||||||
|
assertSame( factory, typeFactory.resolveSessionFactory() );
|
||||||
|
factory.close();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testUnregisterSerializeRegisterSameSessionFactoryNoName() throws Exception {
|
||||||
|
Configuration cfg = new Configuration();
|
||||||
|
SessionFactoryImplementor factory = (SessionFactoryImplementor) cfg.buildSessionFactory();
|
||||||
|
assertSame( factory, SessionFactoryRegistry.INSTANCE.findSessionFactory( factory.getUuid(), null ) );
|
||||||
|
|
||||||
|
// Remove the session factory from the registry
|
||||||
|
SessionFactoryRegistry.INSTANCE.removeSessionFactory( factory.getUuid(), null, false, null );
|
||||||
|
assertNull( SessionFactoryRegistry.INSTANCE.findSessionFactory( factory.getUuid(), null ) );
|
||||||
|
|
||||||
|
TypeFactory typeFactory = factory.getTypeResolver().getTypeFactory();
|
||||||
|
byte[] typeFactoryBytes = SerializationHelper.serialize( typeFactory );
|
||||||
|
typeFactory = (TypeFactory) SerializationHelper.deserialize( typeFactoryBytes );
|
||||||
|
|
||||||
|
try {
|
||||||
|
typeFactory.resolveSessionFactory();
|
||||||
|
fail( "should have failed with HibernateException because session factory is not registered." );
|
||||||
|
}
|
||||||
|
catch ( HibernateException ex ) {
|
||||||
|
// expected because the session factory is not registered.
|
||||||
|
}
|
||||||
|
|
||||||
|
// Re-register the same session factory.
|
||||||
|
SessionFactoryRegistry.INSTANCE.addSessionFactory( factory.getUuid(), null, false, factory, null );
|
||||||
|
|
||||||
|
// Session factory resolved from typeFactory should be the new session factory
|
||||||
|
// (because it is resolved from SessionFactoryRegistry.INSTANCE)
|
||||||
|
assertSame( factory, typeFactory.resolveSessionFactory() );
|
||||||
|
factory.close();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testUnregisterSerializeRegisterDiffSessionFactory() throws Exception {
|
||||||
|
Configuration cfg = new Configuration()
|
||||||
|
.setProperty( AvailableSettings.SESSION_FACTORY_NAME, NAME )
|
||||||
|
.setProperty( AvailableSettings.SESSION_FACTORY_NAME_IS_JNDI, "false" ); // default is true
|
||||||
|
SessionFactoryImplementor factory = (SessionFactoryImplementor) cfg.buildSessionFactory();
|
||||||
|
assertSame( factory, SessionFactoryRegistry.INSTANCE.getNamedSessionFactory( NAME ) );
|
||||||
|
|
||||||
|
// Remove the session factory from the registry
|
||||||
|
SessionFactoryRegistry.INSTANCE.removeSessionFactory( factory.getUuid(), NAME, false, null );
|
||||||
|
assertNull( SessionFactoryRegistry.INSTANCE.findSessionFactory( factory.getUuid(), NAME ) );
|
||||||
|
|
||||||
|
TypeFactory typeFactory = factory.getTypeResolver().getTypeFactory();
|
||||||
|
byte[] typeFactoryBytes = SerializationHelper.serialize( typeFactory );
|
||||||
|
typeFactory = (TypeFactory) SerializationHelper.deserialize( typeFactoryBytes );
|
||||||
|
|
||||||
|
try {
|
||||||
|
typeFactory.resolveSessionFactory();
|
||||||
|
fail( "should have failed with HibernateException because session factory is not registered." );
|
||||||
|
}
|
||||||
|
catch ( HibernateException ex ) {
|
||||||
|
// expected because the session factory is not registered.
|
||||||
|
}
|
||||||
|
|
||||||
|
// Now create a new session factory with the same name; it will have a different UUID.
|
||||||
|
SessionFactoryImplementor factoryWithSameName = (SessionFactoryImplementor) cfg.buildSessionFactory();
|
||||||
|
assertSame( factoryWithSameName, SessionFactoryRegistry.INSTANCE.getNamedSessionFactory( NAME ) );
|
||||||
|
assertFalse( factory.getUuid().equals( factoryWithSameName.getUuid() ) );
|
||||||
|
|
||||||
|
// Session factory resolved from typeFactory should be the new session factory
|
||||||
|
// (because it is resolved from SessionFactoryRegistry.INSTANCE)
|
||||||
|
assertSame( factoryWithSameName, typeFactory.resolveSessionFactory() );
|
||||||
|
|
||||||
|
factory.close();
|
||||||
|
factoryWithSameName.close();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testUnregisterSerializeRegisterDiffSessionFactoryNoName() throws Exception {
|
||||||
|
Configuration cfg = new Configuration();
|
||||||
|
SessionFactoryImplementor factory = (SessionFactoryImplementor) cfg.buildSessionFactory();
|
||||||
|
assertSame( factory, SessionFactoryRegistry.INSTANCE.getSessionFactory( factory.getUuid() ) );
|
||||||
|
|
||||||
|
// Remove the session factory from the registry
|
||||||
|
SessionFactoryRegistry.INSTANCE.removeSessionFactory( factory.getUuid(), null, false, null );
|
||||||
|
assertNull( SessionFactoryRegistry.INSTANCE.getSessionFactory( factory.getUuid() ) );
|
||||||
|
|
||||||
|
TypeFactory typeFactory = factory.getTypeResolver().getTypeFactory();
|
||||||
|
byte[] typeFactoryBytes = SerializationHelper.serialize( typeFactory );
|
||||||
|
typeFactory = (TypeFactory) SerializationHelper.deserialize( typeFactoryBytes );
|
||||||
|
|
||||||
|
try {
|
||||||
|
typeFactory.resolveSessionFactory();
|
||||||
|
fail( "should have failed with HibernateException because session factory is not registered." );
|
||||||
|
}
|
||||||
|
catch ( HibernateException ex ) {
|
||||||
|
// expected because the session factory is not registered.
|
||||||
|
}
|
||||||
|
|
||||||
|
// Now create a new session factory with the same name; it will have a different UUID.
|
||||||
|
SessionFactoryImplementor factoryWithDiffUuid = (SessionFactoryImplementor) cfg.buildSessionFactory();
|
||||||
|
assertSame( factoryWithDiffUuid, SessionFactoryRegistry.INSTANCE.getSessionFactory( factoryWithDiffUuid.getUuid() ) );
|
||||||
|
assertFalse( factory.getUuid().equals( factoryWithDiffUuid.getUuid() ) );
|
||||||
|
|
||||||
|
// It should not be possible to resolve the session factory with no name configured.
|
||||||
|
try {
|
||||||
|
typeFactory.resolveSessionFactory();
|
||||||
|
fail( "should have failed with HibernateException because session factories were not registered with the same non-null name." );
|
||||||
|
}
|
||||||
|
catch ( HibernateException ex ) {
|
||||||
|
// expected
|
||||||
|
}
|
||||||
|
|
||||||
|
factory.close();
|
||||||
|
factoryWithDiffUuid.close();
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue