HHH-4841 : Read-only proxies in NonFlushedChanges are not read-only when applied to a new session

git-svn-id: https://svn.jboss.org/repos/hibernate/core/trunk@18699 1b8cb986-b30d-0410-93ca-fae66ebed9b2
This commit is contained in:
Gail Badner 2010-02-05 04:00:04 +00:00
parent 53b1890c1b
commit 8606c4a097
13 changed files with 291 additions and 75 deletions

View File

@ -672,10 +672,19 @@ public class StatefulPersistenceContext implements PersistenceContext {
} }
else { else {
proxy = persister.createProxy( key.getIdentifier(), session ); proxy = persister.createProxy( key.getIdentifier(), session );
proxiesByKey.put(key, proxy); //overwrite old proxy Object proxyOrig = proxiesByKey.put(key, proxy); //overwrite old proxy
if ( proxyOrig != null ) {
if ( ! ( proxyOrig instanceof HibernateProxy ) ) {
throw new AssertionFailure(
"proxy not of type HibernateProxy; it is " + proxyOrig.getClass()
);
}
// set the read-only/modifiable mode in the new proxy to what it was in the original proxy
boolean readOnlyOrig = ( ( HibernateProxy ) proxyOrig ).getHibernateLazyInitializer().isReadOnly();
( ( HibernateProxy ) proxy ).getHibernateLazyInitializer().setReadOnly( readOnlyOrig );
}
return proxy; return proxy;
} }
} }
else { else {

View File

@ -190,13 +190,18 @@ public final class TwoPhaseLoad {
} }
} }
boolean isReallyReadOnly = readOnly || !persister.isMutable(); boolean isReallyReadOnly = readOnly;
if ( !persister.isMutable() ) {
isReallyReadOnly = true;
}
else {
Object proxy = persistenceContext.getProxy( entityEntry.getEntityKey() ); Object proxy = persistenceContext.getProxy( entityEntry.getEntityKey() );
if ( proxy != null ) { if ( proxy != null ) {
// there is already a proxy for this impl // there is already a proxy for this impl
// only set the status to read-only if the proxy is read-only // only set the status to read-only if the proxy is read-only
isReallyReadOnly = ( ( HibernateProxy ) proxy ).getHibernateLazyInitializer().isReadOnly(); isReallyReadOnly = ( ( HibernateProxy ) proxy ).getHibernateLazyInitializer().isReadOnly();
} }
}
if ( isReallyReadOnly ) { if ( isReallyReadOnly ) {
//no need to take a snapshot - this is a //no need to take a snapshot - this is a
//performance optimization, but not really //performance optimization, but not really

View File

@ -360,9 +360,6 @@ public class DefaultLoadEventListener extends AbstractLockUpgradeEventListener i
Object proxy = persister.createProxy( event.getEntityId(), event.getSession() ); Object proxy = persister.createProxy( event.getEntityId(), event.getSession() );
persistenceContext.getBatchFetchQueue().addBatchLoadableEntityKey(keyToLoad); persistenceContext.getBatchFetchQueue().addBatchLoadableEntityKey(keyToLoad);
persistenceContext.addProxy(keyToLoad, proxy); persistenceContext.addProxy(keyToLoad, proxy);
( ( HibernateProxy ) proxy )
.getHibernateLazyInitializer()
.setReadOnly( event.getSession().isDefaultReadOnly() || ! persister.isMutable() );
return proxy; return proxy;
} }
} }

View File

@ -26,12 +26,14 @@ package org.hibernate.proxy;
import java.io.Serializable; import java.io.Serializable;
import org.hibernate.AssertionFailure;
import org.hibernate.HibernateException; import org.hibernate.HibernateException;
import org.hibernate.LazyInitializationException; import org.hibernate.LazyInitializationException;
import org.hibernate.TransientObjectException; import org.hibernate.TransientObjectException;
import org.hibernate.SessionException; import org.hibernate.SessionException;
import org.hibernate.engine.EntityKey; import org.hibernate.engine.EntityKey;
import org.hibernate.engine.SessionImplementor; import org.hibernate.engine.SessionImplementor;
import org.hibernate.persister.entity.EntityPersister;
/** /**
* Convenience base class for lazy initialization handlers. Centralizes the basic plumbing of doing lazy * Convenience base class for lazy initialization handlers. Centralizes the basic plumbing of doing lazy
@ -48,6 +50,7 @@ public abstract class AbstractLazyInitializer implements LazyInitializer {
private boolean readOnly; private boolean readOnly;
private boolean unwrap; private boolean unwrap;
private transient SessionImplementor session; private transient SessionImplementor session;
private Boolean readOnlyBeforeAttachedToSession;
/** /**
* For serialization from the non-pojo initializers (HHH-3309) * For serialization from the non-pojo initializers (HHH-3309)
@ -65,11 +68,9 @@ public abstract class AbstractLazyInitializer implements LazyInitializer {
protected AbstractLazyInitializer(String entityName, Serializable id, SessionImplementor session) { protected AbstractLazyInitializer(String entityName, Serializable id, SessionImplementor session) {
this.entityName = entityName; this.entityName = entityName;
this.id = id; this.id = id;
this.readOnly = false;
// initialize other fields depending on session state // initialize other fields depending on session state
if ( session == null ) { if ( session == null ) {
// would be better to call unsetSession(), but it is not final... unsetSession();
session = null;
} }
else { else {
setSession( session ); setSession( session );
@ -116,18 +117,27 @@ public abstract class AbstractLazyInitializer implements LazyInitializer {
*/ */
public final void setSession(SessionImplementor s) throws HibernateException { public final void setSession(SessionImplementor s) throws HibernateException {
if ( s != session ) { if ( s != session ) {
readOnly = false;
// check for s == null first, since it is least expensive // check for s == null first, since it is least expensive
if ( s == null ){ if ( s == null ){
// would be better to call unsetSession(), but it is not final... unsetSession();
session = null;
} }
else if ( isConnectedToSession() ) { else if ( isConnectedToSession() ) {
//TODO: perhaps this should be some other RuntimeException... //TODO: perhaps this should be some other RuntimeException...
throw new HibernateException("illegally attempted to associate a proxy with two open Sessions"); throw new HibernateException("illegally attempted to associate a proxy with two open Sessions");
} }
else { else {
// s != null
session = s; session = s;
if ( readOnlyBeforeAttachedToSession == null ) {
// use the default read-only/modifiable setting
final EntityPersister persister = s.getFactory().getEntityPersister( entityName );
setReadOnly( s.getPersistenceContext().isDefaultReadOnly() || ! persister.isMutable() );
}
else {
// use the read-only/modifiable setting indicated during deserialization
setReadOnly( readOnlyBeforeAttachedToSession.booleanValue() );
readOnlyBeforeAttachedToSession = null;
}
} }
} }
} }
@ -142,9 +152,10 @@ public abstract class AbstractLazyInitializer implements LazyInitializer {
/** /**
* {@inheritDoc} * {@inheritDoc}
*/ */
public void unsetSession() { public final void unsetSession() {
session = null; session = null;
readOnly = false; readOnly = false;
readOnlyBeforeAttachedToSession = null;
} }
/** /**
@ -236,32 +247,8 @@ public abstract class AbstractLazyInitializer implements LazyInitializer {
/** /**
* {@inheritDoc} * {@inheritDoc}
*/ */
public boolean isReadOnly() { public final boolean isReadOnlySettingAvailable() {
errorIfReadOnlySettingNotAvailable(); return ( session != null && ! session.isClosed() );
if ( !isConnectedToSession() ) {
throw new TransientObjectException(
"The read-only/modifiable setting is only accessible when the proxy is associated with a session." );
}
return readOnly;
}
/**
* {@inheritDoc}
*/
public void setReadOnly(boolean readOnly) {
errorIfReadOnlySettingNotAvailable();
// only update if readOnly is different from current setting
if ( this.readOnly != readOnly ) {
Object proxy = getProxyOrNull();
if ( proxy == null ) {
throw new TransientObjectException(
"Cannot set the read-only/modifiable mode unless the proxy is associated with a session." );
}
this.readOnly = readOnly;
if ( initialized ) {
session.getPersistenceContext().setReadOnly( target, readOnly );
}
}
} }
private void errorIfReadOnlySettingNotAvailable() { private void errorIfReadOnlySettingNotAvailable() {
@ -275,6 +262,77 @@ public abstract class AbstractLazyInitializer implements LazyInitializer {
} }
} }
/**
* {@inheritDoc}
*/
public final boolean isReadOnly() {
errorIfReadOnlySettingNotAvailable();
return readOnly;
}
/**
* {@inheritDoc}
*/
public final void setReadOnly(boolean readOnly) {
errorIfReadOnlySettingNotAvailable();
// only update if readOnly is different from current setting
if ( this.readOnly != readOnly ) {
final EntityPersister persister = session.getFactory().getEntityPersister( entityName );
if ( ! persister.isMutable() && ! readOnly ) {
throw new IllegalStateException( "cannot make proxies for immutable entities modifiable");
}
this.readOnly = readOnly;
if ( initialized ) {
EntityKey key = generateEntityKeyOrNull( getIdentifier(), session, getEntityName() );
if ( key != null && session.getPersistenceContext().containsEntity( key ) ) {
session.getPersistenceContext().setReadOnly( target, readOnly );
}
}
}
}
/**
* Get the read-only/modifiable setting that should be put in affect when it is
* attached to a session.
*
* This method should only be called during serialization when read-only/modifiable setting
* is not available (i.e., isReadOnlySettingAvailable() == false)
*
* @returns, null, if the default setting should be used;
* true, for read-only;
* false, for modifiable
* @throws IllegalStateException if isReadOnlySettingAvailable() == true
*/
protected final Boolean isReadOnlyBeforeAttachedToSession() {
if ( isReadOnlySettingAvailable() ) {
throw new IllegalStateException(
"Cannot call isReadOnlyBeforeAttachedToSession when isReadOnlySettingAvailable == true"
);
}
return readOnlyBeforeAttachedToSession;
}
/**
* Set the read-only/modifiable setting that should be put in affect when it is
* attached to a session.
*
* This method should only be called during deserialization, before associating
* the proxy with a session.
*
* @param readOnlyBeforeAttachedToSession, the read-only/modifiable setting to use when
* associated with a session; null indicates that the default should be used.
* @throws IllegalStateException if isReadOnlySettingAvailable() == true
*/
/* package-private */
final void setReadOnlyBeforeAttachedToSession(Boolean readOnlyBeforeAttachedToSession) {
if ( isReadOnlySettingAvailable() ) {
throw new IllegalStateException(
"Cannot call setReadOnlyBeforeAttachedToSession when isReadOnlySettingAvailable == true"
);
}
this.readOnlyBeforeAttachedToSession = readOnlyBeforeAttachedToSession;
}
/** /**
* {@inheritDoc} * {@inheritDoc}
*/ */

View File

@ -0,0 +1,72 @@
/*
* Hibernate, Relational Persistence for Idiomatic Java
*
* Copyright (c) 2010, Red Hat Middleware LLC or third-party contributors as
* indicated by the @author tags or express copyright attribution
* statements applied by the authors. All third-party contributions are
* distributed under license by Red Hat Middleware LLC.
*
* This copyrighted material is made available to anyone wishing to use, modify,
* copy, or redistribute it subject to the terms and conditions of the GNU
* Lesser General Public License, as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
* for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this distribution; if not, write to:
* Free Software Foundation, Inc.
* 51 Franklin Street, Fifth Floor
* Boston, MA 02110-1301 USA
*
*/
package org.hibernate.proxy;
import java.io.Serializable;
/**
* Convenience base class for SerializableProxy.
*
* @author Gail Badner
*/
public abstract class AbstractSerializableProxy implements Serializable {
private String entityName;
private Serializable id;
private Boolean readOnly;
/**
* For serialization
*/
protected AbstractSerializableProxy() {
}
protected AbstractSerializableProxy(String entityName, Serializable id, Boolean readOnly) {
this.entityName = entityName;
this.id = id;
this.readOnly = readOnly;
}
protected String getEntityName() {
return entityName;
}
protected Serializable getId() {
return id;
}
/**
* Set the read-only/modifiable setting from this object in an AbstractLazyInitializer.
*
* This method should only be called during deserialization, before associating the
* AbstractLazyInitializer with a session.
*
* @param li, the read-only/modifiable setting to use when
* associated with a session; null indicates that the default should be used.
* @throws IllegalStateException if isReadOnlySettingAvailable() == true
*/
protected void setReadOnlyBeforeAttachedToSession(AbstractLazyInitializer li) {
li.setReadOnlyBeforeAttachedToSession( readOnly );
}
}

View File

@ -104,11 +104,24 @@ public interface LazyInitializer {
*/ */
public void setImplementation(Object target); public void setImplementation(Object target);
/**
* Is the proxy's read-only/modifiable setting available?
* @return true, if the setting is available
* false, if the proxy is detached or its associated session is closed
*/
public boolean isReadOnlySettingAvailable();
/** /**
* Is the proxy read-only?. * Is the proxy read-only?.
* *
* The read-only/modifiable setting is not available when the proxy is
* detached or its associated session is closed.
*
* To check if the read-only/modifiable setting is available:
* @see org.hibernate.proxy.LazyInitializer#isReadOnlySettingAvailable()
*
* @return true, if this proxy is read-only; false, otherwise * @return true, if this proxy is read-only; false, otherwise
* @throws org.hibernate.TransientObjectException if the proxy is not association with a session * @throws org.hibernate.TransientObjectException if the proxy is detached (getSession() == null)
* @throws org.hibernate.SessionException if the proxy is associated with a sesssion that is closed * @throws org.hibernate.SessionException if the proxy is associated with a sesssion that is closed
* *
* @see org.hibernate.Session#isReadOnly(Object entityOrProxy) * @see org.hibernate.Session#isReadOnly(Object entityOrProxy)

View File

@ -212,11 +212,10 @@ public final class CGLIBLazyInitializer extends BasicLazyInitializer implements
persistentClass, persistentClass,
interfaces, interfaces,
getIdentifier(), getIdentifier(),
( getSession() != null && getSession().isOpen() ? isReadOnly() : false ), ( isReadOnlySettingAvailable() ? Boolean.valueOf( isReadOnly() ) : isReadOnlyBeforeAttachedToSession() ),
getIdentifierMethod, getIdentifierMethod,
setIdentifierMethod, setIdentifierMethod,
componentIdType componentIdType
); );
} }
} }

View File

@ -28,19 +28,17 @@ import java.io.Serializable;
import java.lang.reflect.Method; import java.lang.reflect.Method;
import org.hibernate.HibernateException; import org.hibernate.HibernateException;
import org.hibernate.proxy.AbstractSerializableProxy;
import org.hibernate.proxy.HibernateProxy; import org.hibernate.proxy.HibernateProxy;
import org.hibernate.type.AbstractComponentType; import org.hibernate.type.AbstractComponentType;
/** /**
* Serializable placeholder for <tt>CGLIB</tt> proxies * Serializable placeholder for <tt>CGLIB</tt> proxies
*/ */
public final class SerializableProxy implements Serializable { public final class SerializableProxy extends AbstractSerializableProxy {
private String entityName;
private Class persistentClass; private Class persistentClass;
private Class[] interfaces; private Class[] interfaces;
private Serializable id;
private boolean readOnly;
private Class getIdentifierMethodClass; private Class getIdentifierMethodClass;
private Class setIdentifierMethodClass; private Class setIdentifierMethodClass;
private String getIdentifierMethodName; private String getIdentifierMethodName;
@ -55,16 +53,14 @@ public final class SerializableProxy implements Serializable {
final Class persistentClass, final Class persistentClass,
final Class[] interfaces, final Class[] interfaces,
final Serializable id, final Serializable id,
final boolean readOnly, final Boolean readOnly,
final Method getIdentifierMethod, final Method getIdentifierMethod,
final Method setIdentifierMethod, final Method setIdentifierMethod,
AbstractComponentType componentIdType AbstractComponentType componentIdType
) { ) {
this.entityName = entityName; super( entityName, id, readOnly );
this.persistentClass = persistentClass; this.persistentClass = persistentClass;
this.interfaces = interfaces; this.interfaces = interfaces;
this.id = id;
this.readOnly = readOnly;
if (getIdentifierMethod!=null) { if (getIdentifierMethod!=null) {
getIdentifierMethodClass = getIdentifierMethod.getDeclaringClass(); getIdentifierMethodClass = getIdentifierMethod.getDeclaringClass();
getIdentifierMethodName = getIdentifierMethod.getName(); getIdentifierMethodName = getIdentifierMethod.getName();
@ -79,8 +75,8 @@ public final class SerializableProxy implements Serializable {
private Object readResolve() { private Object readResolve() {
try { try {
return CGLIBLazyInitializer.getProxy( HibernateProxy proxy = CGLIBLazyInitializer.getProxy(
entityName, getEntityName(),
persistentClass, persistentClass,
interfaces, interfaces,
getIdentifierMethodName==null ? getIdentifierMethodName==null ?
@ -90,12 +86,15 @@ public final class SerializableProxy implements Serializable {
null : null :
setIdentifierMethodClass.getDeclaredMethod(setIdentifierMethodName, setIdentifierMethodParams), setIdentifierMethodClass.getDeclaredMethod(setIdentifierMethodName, setIdentifierMethodParams),
componentIdType, componentIdType,
id, getId(),
null null
); );
setReadOnlyBeforeAttachedToSession( ( CGLIBLazyInitializer ) proxy.getHibernateLazyInitializer() );
return proxy;
} }
catch (NoSuchMethodException nsme) { catch (NoSuchMethodException nsme) {
throw new HibernateException("could not create proxy for entity: " + entityName, nsme); throw new HibernateException("could not create proxy for entity: " + getEntityName(), nsme);
} }
} }

View File

@ -34,6 +34,7 @@ import javassist.util.proxy.ProxyFactory;
import javassist.util.proxy.ProxyObject; import javassist.util.proxy.ProxyObject;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
import org.hibernate.HibernateException; import org.hibernate.HibernateException;
import org.hibernate.engine.SessionImplementor; import org.hibernate.engine.SessionImplementor;
import org.hibernate.proxy.pojo.BasicLazyInitializer; import org.hibernate.proxy.pojo.BasicLazyInitializer;
@ -229,7 +230,7 @@ public class JavassistLazyInitializer extends BasicLazyInitializer implements Me
persistentClass, persistentClass,
interfaces, interfaces,
getIdentifier(), getIdentifier(),
( getSession() != null && getSession().isOpen() ? isReadOnly() : false ), ( isReadOnlySettingAvailable() ? Boolean.valueOf( isReadOnly() ) : isReadOnlyBeforeAttachedToSession() ),
getIdentifierMethod, getIdentifierMethod,
setIdentifierMethod, setIdentifierMethod,
componentIdType componentIdType

View File

@ -28,19 +28,17 @@ import java.io.Serializable;
import java.lang.reflect.Method; import java.lang.reflect.Method;
import org.hibernate.HibernateException; import org.hibernate.HibernateException;
import org.hibernate.proxy.AbstractSerializableProxy;
import org.hibernate.proxy.HibernateProxy; import org.hibernate.proxy.HibernateProxy;
import org.hibernate.type.AbstractComponentType; import org.hibernate.type.AbstractComponentType;
/** /**
* Serializable placeholder for Javassist proxies * Serializable placeholder for Javassist proxies
*/ */
public final class SerializableProxy implements Serializable { public final class SerializableProxy extends AbstractSerializableProxy {
private String entityName;
private Class persistentClass; private Class persistentClass;
private Class[] interfaces; private Class[] interfaces;
private Serializable id;
private boolean readOnly;
private Class getIdentifierMethodClass; private Class getIdentifierMethodClass;
private Class setIdentifierMethodClass; private Class setIdentifierMethodClass;
private String getIdentifierMethodName; private String getIdentifierMethodName;
@ -55,16 +53,14 @@ public final class SerializableProxy implements Serializable {
final Class persistentClass, final Class persistentClass,
final Class[] interfaces, final Class[] interfaces,
final Serializable id, final Serializable id,
final boolean readOnly, final Boolean readOnly,
final Method getIdentifierMethod, final Method getIdentifierMethod,
final Method setIdentifierMethod, final Method setIdentifierMethod,
AbstractComponentType componentIdType AbstractComponentType componentIdType
) { ) {
this.entityName = entityName; super( entityName, id, readOnly );
this.persistentClass = persistentClass; this.persistentClass = persistentClass;
this.interfaces = interfaces; this.interfaces = interfaces;
this.id = id;
this.readOnly = readOnly;
if (getIdentifierMethod!=null) { if (getIdentifierMethod!=null) {
getIdentifierMethodClass = getIdentifierMethod.getDeclaringClass(); getIdentifierMethodClass = getIdentifierMethod.getDeclaringClass();
getIdentifierMethodName = getIdentifierMethod.getName(); getIdentifierMethodName = getIdentifierMethod.getName();
@ -79,8 +75,8 @@ public final class SerializableProxy implements Serializable {
private Object readResolve() { private Object readResolve() {
try { try {
return JavassistLazyInitializer.getProxy( HibernateProxy proxy = JavassistLazyInitializer.getProxy(
entityName, getEntityName(),
persistentClass, persistentClass,
interfaces, interfaces,
getIdentifierMethodName==null ? getIdentifierMethodName==null ?
@ -90,13 +86,14 @@ public final class SerializableProxy implements Serializable {
null : null :
setIdentifierMethodClass.getDeclaredMethod(setIdentifierMethodName, setIdentifierMethodParams), setIdentifierMethodClass.getDeclaredMethod(setIdentifierMethodName, setIdentifierMethodParams),
componentIdType, componentIdType,
id, getId(),
null null
); );
setReadOnlyBeforeAttachedToSession( ( JavassistLazyInitializer ) proxy.getHibernateLazyInitializer() );
return proxy;
} }
catch (NoSuchMethodException nsme) { catch (NoSuchMethodException nsme) {
throw new HibernateException("could not create proxy for entity: " + entityName, nsme); throw new HibernateException("could not create proxy for entity: " + getEntityName(), nsme);
} }
} }
} }

View File

@ -185,7 +185,7 @@ public class GetLoadTest extends AbstractOperationTestCase {
SimpleJtaTransactionManagerImpl.getInstance().commit(); SimpleJtaTransactionManagerImpl.getInstance().commit();
} }
public void testLoadReadOnlyFailureExpected() throws Exception { public void testLoadReadOnly() throws Exception {
clearCounts(); clearCounts();
SimpleJtaTransactionManagerImpl.getInstance().begin(); SimpleJtaTransactionManagerImpl.getInstance().begin();

View File

@ -123,6 +123,31 @@ public class ProxyTest extends FunctionalTestCase {
s.close(); s.close();
} }
public void testInitializedProxySerializationAfterSessionClosed() {
Session s = openSession();
Transaction t = s.beginTransaction();
DataPoint dp = new DataPoint();
dp.setDescription("a data point");
dp.setX( new BigDecimal(1.0) );
dp.setY( new BigDecimal(2.0) );
s.persist(dp);
s.flush();
s.clear();
dp = (DataPoint) s.load( DataPoint.class, new Long( dp.getId() ) );
assertFalse( Hibernate.isInitialized(dp) );
Hibernate.initialize( dp );
assertTrue( Hibernate.isInitialized(dp) );
s.close();
SerializationHelper.clone( dp );
s = openSession();
t = s.beginTransaction();
s.delete( dp );
t.commit();
s.close();
}
public void testProxySerialization() { public void testProxySerialization() {
Session s = openSession(); Session s = openSession();
Transaction t = s.beginTransaction(); Transaction t = s.beginTransaction();

View File

@ -1328,6 +1328,7 @@ public class ReadOnlyProxyTest extends FunctionalTestCase {
} }
catch ( SessionException ex) { catch ( SessionException ex) {
// expected // expected
assertFalse( ( ( HibernateProxy ) dp ).getHibernateLazyInitializer().isReadOnlySettingAvailable() );
} }
finally { finally {
s = openSession(); s = openSession();
@ -1360,6 +1361,7 @@ public class ReadOnlyProxyTest extends FunctionalTestCase {
} }
catch ( TransientObjectException ex) { catch ( TransientObjectException ex) {
// expected // expected
assertFalse( ( ( HibernateProxy ) dp ).getHibernateLazyInitializer().isReadOnlySettingAvailable() );
} }
finally { finally {
s = openSession(); s = openSession();
@ -1393,6 +1395,7 @@ public class ReadOnlyProxyTest extends FunctionalTestCase {
} }
catch ( TransientObjectException ex) { catch ( TransientObjectException ex) {
// expected // expected
assertFalse( ( ( HibernateProxy ) dp ).getHibernateLazyInitializer().isReadOnlySettingAvailable() );
} }
finally { finally {
s.delete( dp ); s.delete( dp );
@ -1421,6 +1424,7 @@ public class ReadOnlyProxyTest extends FunctionalTestCase {
} }
catch ( TransientObjectException ex) { catch ( TransientObjectException ex) {
// expected // expected
assertFalse( ( ( HibernateProxy ) dp ).getHibernateLazyInitializer().isReadOnlySettingAvailable() );
} }
finally { finally {
s.beginTransaction(); s.beginTransaction();
@ -1450,6 +1454,7 @@ public class ReadOnlyProxyTest extends FunctionalTestCase {
} }
catch ( SessionException ex) { catch ( SessionException ex) {
// expected // expected
assertFalse( ( ( HibernateProxy ) dp ).getHibernateLazyInitializer().isReadOnlySettingAvailable() );
} }
finally { finally {
s = openSession(); s = openSession();
@ -1482,6 +1487,7 @@ public class ReadOnlyProxyTest extends FunctionalTestCase {
} }
catch ( TransientObjectException ex) { catch ( TransientObjectException ex) {
// expected // expected
assertFalse( ( ( HibernateProxy ) dp ).getHibernateLazyInitializer().isReadOnlySettingAvailable() );
} }
finally { finally {
s = openSession(); s = openSession();
@ -1492,6 +1498,39 @@ public class ReadOnlyProxyTest extends FunctionalTestCase {
} }
} }
public void testSetClosedSessionInLazyInitializer() {
DataPoint dpOrig = createDataPoint( CacheMode.IGNORE );
Session s = openSession();
s.setCacheMode(CacheMode.IGNORE);
s.beginTransaction();
DataPoint dp = ( DataPoint ) s.load( DataPoint.class, new Long( dpOrig.getId() ) );
assertTrue( dp instanceof HibernateProxy );
assertFalse( Hibernate.isInitialized( dp ) );
checkReadOnly( s, dp, false );
s.getTransaction().commit();
assertTrue( s.contains( dp ) );
s.close();
assertNull( ( ( HibernateProxy ) dp ).getHibernateLazyInitializer().getSession() );
assertTrue( ( ( SessionImplementor ) s ).isClosed() );
try {
( ( HibernateProxy ) dp ).getHibernateLazyInitializer().setSession( ( SessionImplementor ) s );
fail( "should have failed because session was closed" );
}
catch ( SessionException ex) {
// expected
assertFalse( ( ( HibernateProxy ) dp ).getHibernateLazyInitializer().isReadOnlySettingAvailable() );
}
finally {
s = openSession();
s.beginTransaction();
s.delete( dp );
s.getTransaction().commit();
s.close();
}
}
public void testDetachedSetReadOnlyAfterEvictViaSession() { public void testDetachedSetReadOnlyAfterEvictViaSession() {
DataPoint dpOrig = createDataPoint( CacheMode.IGNORE ); DataPoint dpOrig = createDataPoint( CacheMode.IGNORE );
@ -1515,6 +1554,7 @@ public class ReadOnlyProxyTest extends FunctionalTestCase {
} }
catch ( TransientObjectException ex) { catch ( TransientObjectException ex) {
// expected // expected
assertFalse( ( ( HibernateProxy ) dp ).getHibernateLazyInitializer().isReadOnlySettingAvailable() );
} }
finally { finally {
s.delete( dp ); s.delete( dp );
@ -1543,6 +1583,7 @@ public class ReadOnlyProxyTest extends FunctionalTestCase {
} }
catch ( TransientObjectException ex) { catch ( TransientObjectException ex) {
// expected // expected
assertFalse( ( ( HibernateProxy ) dp ).getHibernateLazyInitializer().isReadOnlySettingAvailable() );
} }
finally { finally {
s.beginTransaction(); s.beginTransaction();