HHH-2501 HHH-4804 : Add default read-only/modifiable setting for session; fix setting for non-lazy associations loaded from Query

git-svn-id: https://svn.jboss.org/repos/hibernate/core/trunk@18641 1b8cb986-b30d-0410-93ca-fae66ebed9b2
This commit is contained in:
Gail Badner 2010-01-27 06:36:55 +00:00
parent 3b536fa6f6
commit a0d8e6a415
25 changed files with 3055 additions and 40 deletions

View File

@ -175,11 +175,46 @@ public interface Query {
public Query setFirstResult(int firstResult);
/**
* Entities retrieved by this query will be loaded in
* a read-only mode where Hibernate will never dirty-check
* them or make changes persistent.
* Should entities and proxies loaded by this Query be put in read-only mode? If the
* read-only/modifiable setting was not initialized, then the default
* read-only/modifiable setting for the persistence context is returned instead.
* @see Query#setReadOnly(boolean)
* @see org.hibernate.engine.PersistenceContext#isDefaultReadOnly()
*
* The read-only/modifiable setting has no impact on entities/proxies returned by the
* query that existed in the session before the query was executed.
*
* @return true, entities and proxies loaded by the query will be put in read-only mode
* false, entities and proxies loaded by the query will be put in modifiable mode
*/
public boolean isReadOnly();
/**
* Set the read-only/modifiable mode for entities and proxies
* loaded by this Query. This setting overrides the default setting
* for the persistence context.
* @see org.hibernate.engine.PersistenceContext#isDefaultReadOnly()
*
* To set the default read-only/modifiable setting used for
* entities and proxies that are loaded into the session:
* @see org.hibernate.engine.PersistenceContext#setDefaultReadOnly(boolean)
* @see org.hibernate.Session#setDefaultReadOnly(boolean)
*
* Read-only entities are not dirty-checked and snapshots of persistent
* state are not maintained. Read-only entities can be modified, but
* changes are not persisted.
*
* When a proxy is initialized, the loaded entity will have the same
* read-only/modifiable setting as the uninitialized
* proxy has, regardless of the session's current setting.
*
* The read-only/modifiable setting has no impact on entities/proxies
* returned by the query that existed in the session before the query was executed.
*
* @return true, entities and proxies loaded by the query will be put in read-only mode
* false, entities and proxies loaded by the query will be put in modifiable mode
*/
public Query setReadOnly(boolean readOnly);
/**

View File

@ -231,6 +231,44 @@ public interface Session extends Serializable {
*/
public boolean isDirty() throws HibernateException;
/**
* Will entities and proxies that are loaded into this session be made
* read-only by default?
*
* To determine the read-only/modifiable setting for a particular entity
* or proxy:
* @see Session#isReadOnly(Object)
*
* @return true, loaded entities/proxies will be made read-only by default;
* false, loaded entities/proxies will be made modifiable by default.
*/
public boolean isDefaultReadOnly();
/**
* Change the default for entities and proxies loaded into this session
* from modifiable to read-only mode, or from modifiable to read-only mode.
*
* Read-only entities are not dirty-checked and snapshots of persistent
* state are not maintained. Read-only entities can be modified, but
* changes are not persisted.
*
* When a proxy is initialized, the loaded entity will have the same
* read-only/modifiable setting as the uninitialized
* proxy has, regardless of the session's current setting.
*
* To change the read-only/modifiable setting for a particular entity
* or proxy that is already in this session:
* @see Session#setReadOnly(Object,boolean)
*
* To override this session's read-only/modifiable setting for entities
* and proxies loaded by a Query:
* @see Query#setReadOnly(boolean)
*
* @param readOnly true, the default for loaded entities/proxies is read-only;
* false, the default for loaded entities/proxies is modifiable
*/
public void setDefaultReadOnly(boolean readOnly);
/**
* Return the identifier value of the given entity as associated with this
* session. An exception is thrown if the given entity instance is transient
@ -842,6 +880,11 @@ public interface Session extends Serializable {
/**
* Is the specified entity or proxy read-only?
*
* To get the default read-only/modifiable setting used for
* entities and proxies that are loaded into the session:
* @see org.hibernate.Session#isDefaultReadOnly()
*
* @param entityOrProxy, an entity or HibernateProxy
* @return true, the entity or proxy is read-only;
* false, the entity or proxy is modifiable.
@ -850,16 +893,23 @@ public interface Session extends Serializable {
/**
* Set an unmodified persistent object to read-only mode, or a read-only
* object to modifiable mode. In read-only mode, no snapshot is maintained
* and the instance is never dirty checked.
* object to modifiable mode. In read-only mode, no snapshot is maintained,
* the instance is never dirty checked, and changes are not persisted.
*
* If the entity or proxy already has the specified read-only/modifiable
* setting, then this method does nothing.
*
* To set the default read-only/modifiable setting used for
* entities and proxies that are loaded into the session:
* @see org.hibernate.Session#setDefaultReadOnly(boolean)
*
* To override this session's read-only/modifiable setting for entities
* and proxies loaded by a Query:
* @see Query#setReadOnly(boolean)
*
* @param entityOrProxy, an entity or HibernateProxy
* @param readOnly, if true, the entity or proxy is made read-only;
* if false, the entity or proxy is made modifiable.
* @see Query#setReadOnly(boolean)
*/
public void setReadOnly(Object entityOrProxy, boolean readOnly);

View File

@ -476,23 +476,92 @@ public interface PersistenceContext {
*/
public boolean isPropertyNull(EntityKey ownerKey, String propertyName);
/**
* Will entities and proxies that are loaded into this persistence
* context be made read-only by default?
*
* To determine the read-only/modifiable setting for a particular entity
* or proxy:
* @see PersistenceContext#isReadOnly(Object)
* @see org.hibernate.Session#isReadOnly(Object)
*
* @return true, loaded entities/proxies will be made read-only by default;
* false, loaded entities/proxies will be made modifiable by default.
*
* @see org.hibernate.Session#isDefaultReadOnly()
*/
public boolean isDefaultReadOnly();
/**
* Change the default for entities and proxies loaded into this persistence
* context from modifiable to read-only mode, or from modifiable to read-only
* mode.
*
* Read-only entities are not dirty-checked and snapshots of persistent
* state are not maintained. Read-only entities can be modified, but
* changes are not persisted.
*
* When a proxy is initialized, the loaded entity will have the same
* read-only/modifiable setting as the uninitialized
* proxy has, regardless of the persistence context's current setting.
*
* To change the read-only/modifiable setting for a particular entity
* or proxy that is already in this session:
+ * @see PersistenceContext#setReadOnly(Object,boolean)
* @see org.hibernate.Session#setReadOnly(Object, boolean)
*
* To override this session's read-only/modifiable setting for entities
* and proxies loaded by a Query:
* @see org.hibernate.Query#setReadOnly(boolean)
*
* @param readOnly true, the default for loaded entities/proxies is read-only;
* false, the default for loaded entities/proxies is modifiable
*
* @see org.hibernate.Session#setDefaultReadOnly(boolean)
*/
public void setDefaultReadOnly(boolean readOnly);
/**
* Is the entity or proxy read-only?
*
* To get the default read-only/modifiable setting used for
* entities and proxies that are loaded into the session:
* @see org.hibernate.Session#isDefaultReadOnly()
*
* @param entityOrProxy
* @return true, the object is read-only; false, the object is modifiable.
*/
public boolean isReadOnly(Object entityOrProxy);
/**
* Set the entity or proxy to read only and discard it's snapshot.
* Set an unmodified persistent object to read-only mode, or a read-only
* object to modifiable mode.
*
* Read-only entities are not dirty-checked and snapshots of persistent
* state are not maintained. Read-only entities can be modified, but
* changes are not persisted.
*
* When a proxy is initialized, the loaded entity will have the same
* read-only/modifiable setting as the uninitialized
* proxy has, regardless of the session's current setting.
*
* If the entity or proxy already has the specified read-only/modifiable
* setting, then this method does nothing.
*
* To set the default read-only/modifiable setting used for
* entities and proxies that are loaded into this persistence context:
* @see PersistenceContext#setDefaultReadOnly(boolean)
* @see org.hibernate.Session#setDefaultReadOnly(boolean)
*
* To override this persistence context's read-only/modifiable setting
* for entities and proxies loaded by a Query:
* @see org.hibernate.Query#setReadOnly(boolean)
*
* @param entityOrProxy, an entity or HibernateProxy
* @param readOnly, if true, the entity or proxy is made read-only;
* if false, the entity or proxy is made modifiable.
*
* @see org.hibernate.Session#setReadOnly(Object, boolean)
*/
public void setReadOnly(Object entityOrProxy, boolean readOnly);

View File

@ -66,6 +66,7 @@ public final class QueryParameters {
private Object optionalObject;
private String optionalEntityName;
private Serializable optionalId;
private boolean isReadOnlyInitialized;
private boolean readOnly;
private boolean callable = false;
private boolean autodiscovertypes = false;
@ -124,6 +125,7 @@ public final class QueryParameters {
null,
false,
false,
false,
null,
null,
collectionKeys,
@ -149,6 +151,7 @@ public final class QueryParameters {
lockOptions,
rowSelection,
false,
false,
cacheable,
cacheRegion,
comment,
@ -164,6 +167,7 @@ public final class QueryParameters {
final Map namedParameters,
final LockOptions lockOptions,
final RowSelection rowSelection,
final boolean isReadOnlyInitialized,
final boolean readOnly,
final boolean cacheable,
final String cacheRegion,
@ -181,6 +185,7 @@ public final class QueryParameters {
//this.forceCacheRefresh = forceCacheRefresh;
this.comment = comment;
this.collectionKeys = collectionKeys;
this.isReadOnlyInitialized = isReadOnlyInitialized;
this.readOnly = readOnly;
this.resultTransformer = transformer;
}
@ -191,6 +196,7 @@ public final class QueryParameters {
final Map namedParameters,
final LockOptions lockOptions,
final RowSelection rowSelection,
final boolean isReadOnlyInitialized,
final boolean readOnly,
final boolean cacheable,
final String cacheRegion,
@ -207,6 +213,7 @@ public final class QueryParameters {
namedParameters,
lockOptions,
rowSelection,
isReadOnlyInitialized,
readOnly,
cacheable,
cacheRegion,
@ -351,12 +358,82 @@ public final class QueryParameters {
this.optionalObject = optionalObject;
}
/**
* Has the read-only/modifiable mode been explicitly set?
* @see QueryParameters#setReadOnly(boolean)
* @see QueryParameters#isReadOnly(SessionImplementor)
*
* @return true, the read-only/modifiable mode was explicitly set
* false, the read-only/modifiable mode was not explicitly set
*/
public boolean isReadOnlyInitialized() {
return isReadOnlyInitialized;
}
/**
* Should entities and proxies loaded by the Query be put in read-only mode? The
* read-only/modifiable setting must be initialized via QueryParameters#setReadOnly(boolean)
* before calling this method.
*
* @see QueryParameters#isReadOnlyInitialized()
* @see QueryParameters#isReadOnly(SessionImplementor)
* @see QueryParameters#setReadOnly(boolean)
*
* The read-only/modifiable setting has no impact on entities/proxies returned by the
* query that existed in the session before the query was executed.
*
* @return true, entities and proxies loaded by the Query will be put in read-only mode
* false, entities and proxies loaded by the Query will be put in modifiable mode
* @throws IllegalStateException if the read-only/modifiable setting has not been
* initialized (i.e., isReadOnlyInitialized() == false).
*/
public boolean isReadOnly() {
if ( ! isReadOnlyInitialized() ) {
throw new IllegalStateException( "cannot call isReadOnly() when isReadOnlyInitialized() returns false" );
}
return readOnly;
}
/**
* Should entities and proxies loaded by the Query be put in read-only mode? If the
* read-only/modifiable setting was not initialized
* (i.e., QueryParameters#isReadOnlyInitialized() == false), then the default
* read-only/modifiable setting for the persistence context is returned instead.
*
* @see QueryParameters#isReadOnlyInitialized()
* @see QueryParameters#setReadOnly(boolean)
* @see org.hibernate.engine.PersistenceContext#isDefaultReadOnly()
*
* The read-only/modifiable setting has no impact on entities/proxies returned by the
* query that existed in the session before the query was executed.
*
* @return true, entities and proxies loaded by the query will be put in read-only mode
* false, entities and proxies loaded by the query will be put in modifiable mode
*/
public boolean isReadOnly(SessionImplementor session) {
return ( isReadOnlyInitialized ?
isReadOnly() :
session.getPersistenceContext().isDefaultReadOnly()
);
}
/**
* Set the read-only/modifiable mode for entities and proxies loaded by the query.
* *
* @see QueryParameters#isReadOnlyInitialized()
* @see QueryParameters#isReadOnly(SessionImplementor)
* @see QueryParameters#setReadOnly(boolean)
* @see org.hibernate.engine.PersistenceContext#isDefaultReadOnly()
*
* The read-only/modifiable setting has no impact on entities/proxies returned by the
* query that existed in the session before the query was executed.
*
* @return true, entities and proxies loaded by the query will be put in read-only mode
* false, entities and proxies loaded by the query will be put in modifiable mode
*/
public void setReadOnly(boolean readOnly) {
this.readOnly = readOnly;
this.isReadOnlyInitialized = true;
}
public void setCallable(boolean callable) {
@ -467,6 +544,7 @@ public final class QueryParameters {
this.namedParameters,
this.lockOptions,
selection,
this.isReadOnlyInitialized,
this.readOnly,
this.cacheable,
this.cacheRegion,

View File

@ -127,6 +127,7 @@ public class StatefulPersistenceContext implements PersistenceContext {
private int loadCounter = 0;
private boolean flushing = false;
private boolean defaultReadOnly = false;
private boolean hasNonReadOnlyEntities = false;
private LoadContexts loadContexts;
@ -231,12 +232,27 @@ public class StatefulPersistenceContext implements PersistenceContext {
if ( batchFetchQueue != null ) {
batchFetchQueue.clear();
}
// defaultReadOnly is unaffected by clear()
hasNonReadOnlyEntities = false;
if ( loadContexts != null ) {
loadContexts.cleanup();
}
}
/**
* {@inheritDoc}
*/
public boolean isDefaultReadOnly() {
return defaultReadOnly;
}
/**
* {@inheritDoc}
*/
public void setDefaultReadOnly(boolean defaultReadOnly) {
this.defaultReadOnly = defaultReadOnly;
}
public boolean hasNonReadOnlyEntities() {
return hasNonReadOnlyEntities;
}
@ -1396,6 +1412,7 @@ public class StatefulPersistenceContext implements PersistenceContext {
public void serialize(ObjectOutputStream oos) throws IOException {
log.trace( "serializing persistent-context" );
oos.writeBoolean( defaultReadOnly );
oos.writeBoolean( hasNonReadOnlyEntities );
oos.writeInt( entitiesByKey.size() );
@ -1491,6 +1508,7 @@ public class StatefulPersistenceContext implements PersistenceContext {
// because serialization is used for different things.
try {
rtn.defaultReadOnly = ois.readBoolean();
// todo : we can actually just determine this from the incoming EntityEntry-s
rtn.hasNonReadOnlyEntities = ois.readBoolean();

View File

@ -298,6 +298,9 @@ public class DefaultLoadEventListener extends AbstractLockUpgradeEventListener i
Object proxy = persister.createProxy( event.getEntityId(), event.getSession() );
persistenceContext.getBatchFetchQueue().addBatchLoadableEntityKey(keyToLoad);
persistenceContext.addProxy(keyToLoad, proxy);
( ( HibernateProxy ) proxy )
.getHibernateLazyInitializer()
.setReadOnly( event.getSession().isDefaultReadOnly() || ! persister.isMutable() );
return proxy;
}
}
@ -599,7 +602,10 @@ public class DefaultLoadEventListener extends AbstractLockUpgradeEventListener i
final PersistenceContext persistenceContext = session.getPersistenceContext();
persistenceContext.addEntry(
result,
Status.MANAGED,
( session.isDefaultReadOnly() || ! persister.isMutable() ?
Status.READ_ONLY :
Status.MANAGED
),
values,
null,
id,

View File

@ -101,7 +101,7 @@ public abstract class AbstractQueryImpl implements Query {
private FlushMode sessionFlushMode;
private CacheMode sessionCacheMode;
private Serializable collectionKey;
private boolean readOnly;
private Boolean readOnly;
private ResultTransformer resultTransformer;
public AbstractQueryImpl(
@ -202,12 +202,21 @@ public abstract class AbstractQueryImpl implements Query {
return this;
}
/**
* {@inheritDoc}
*/
public boolean isReadOnly() {
return readOnly;
return ( readOnly == null ?
getSession().getPersistenceContext().isDefaultReadOnly() :
readOnly.booleanValue()
);
}
/**
* {@inheritDoc}
*/
public Query setReadOnly(boolean readOnly) {
this.readOnly = readOnly;
this.readOnly = Boolean.valueOf( readOnly );
return this;
}
@ -881,7 +890,8 @@ public abstract class AbstractQueryImpl implements Query {
namedParams,
getLockOptions(),
getSelection(),
readOnly,
true,
isReadOnly(),
cacheable,
cacheRegion,
comment,

View File

@ -1956,6 +1956,20 @@ public final class SessionImpl extends AbstractSessionImpl
return true;
}
/**
* {@inheritDoc}
*/
public boolean isDefaultReadOnly() {
return persistenceContext.isDefaultReadOnly();
}
/**
* {@inheritDoc}
*/
public void setDefaultReadOnly(boolean defaultReadOnly) {
persistenceContext.setDefaultReadOnly( defaultReadOnly );
}
public boolean isReadOnly(Object entityOrProxy) {
errorIfClosed();
checkTransactionSynchStatus();

View File

@ -483,6 +483,22 @@ public class StatelessSessionImpl extends AbstractSessionImpl
return false;
}
/**
* {@inheritDoc}
*/
public boolean isDefaultReadOnly() {
return false;
}
/**
* {@inheritDoc}
*/
public void setDefaultReadOnly(boolean readOnly) throws HibernateException {
if ( readOnly == true ) {
throw new UnsupportedOperationException();
}
}
/////////////////////////////////////////////////////////////////////////////////////////////////////
//TODO: COPY/PASTE FROM SessionImpl, pull up!

View File

@ -253,8 +253,20 @@ public abstract class Loader {
throws HibernateException, SQLException {
final PersistenceContext persistenceContext = session.getPersistenceContext();
boolean defaultReadOnlyOrig = persistenceContext.isDefaultReadOnly();
if ( queryParameters.isReadOnlyInitialized() ) {
// The read-only/modifiable mode for the query was explicitly set.
// Temporarily set the default read-only/modifiable setting to the query's setting.
persistenceContext.setDefaultReadOnly( queryParameters.isReadOnly() );
}
else {
// The read-only/modifiable setting for the query was not initialized.
// Use the default read-only/modifiable from the persistence context instead.
queryParameters.setReadOnly( persistenceContext.isDefaultReadOnly() );
}
persistenceContext.beforeLoad();
List result;
try {
try {
result = doQuery( session, queryParameters, returnProxies );
}
@ -262,6 +274,11 @@ public abstract class Loader {
persistenceContext.afterLoad();
}
persistenceContext.initializeNonLazyCollections();
}
finally {
// Restore the original default
persistenceContext.setDefaultReadOnly( defaultReadOnlyOrig );
}
return result;
}
@ -312,7 +329,7 @@ public abstract class Loader {
hydratedObjects,
resultSet,
session,
queryParameters.isReadOnly()
queryParameters.isReadOnly( session )
);
session.getPersistenceContext().initializeNonLazyCollections();
return result;
@ -363,7 +380,7 @@ public abstract class Loader {
hydratedObjects,
resultSet,
session,
queryParameters.isReadOnly()
queryParameters.isReadOnly( session )
);
session.getPersistenceContext().initializeNonLazyCollections();
return result;
@ -749,7 +766,7 @@ public abstract class Loader {
session.getBatcher().closeQueryStatement( st, rs );
}
initializeEntitiesAndCollections( hydratedObjects, rs, session, queryParameters.isReadOnly() );
initializeEntitiesAndCollections( hydratedObjects, rs, session, queryParameters.isReadOnly( session ) );
if ( createSubselects ) createSubselects( subselectResultKeys, queryParameters, session );

View File

@ -65,11 +65,11 @@ public abstract class AbstractLazyInitializer implements LazyInitializer {
protected AbstractLazyInitializer(String entityName, Serializable id, SessionImplementor session) {
this.entityName = entityName;
this.id = id;
this.readOnly = false;
// initialize other fields depending on session state
if ( session == null ) {
// would be better to call unsetSession(), but it is not final...
session = null;
readOnly = false;
}
else {
setSession( session );
@ -116,11 +116,11 @@ public abstract class AbstractLazyInitializer implements LazyInitializer {
*/
public final void setSession(SessionImplementor s) throws HibernateException {
if ( s != session ) {
readOnly = false;
// check for s == null first, since it is least expensive
if ( s == null ){
// would be better to call unsetSession(), but it is not final...
session = null;
readOnly = false;
}
else if ( isConnectedToSession() ) {
//TODO: perhaps this should be some other RuntimeException...
@ -128,8 +128,6 @@ public abstract class AbstractLazyInitializer implements LazyInitializer {
}
else {
session = s;
// NOTE: the proxy may not be connected to the session yet, so set readOnly directly
readOnly = ! session.getFactory().getEntityPersister( entityName ).isMutable();
}
}
}

View File

@ -212,6 +212,7 @@ public final class CGLIBLazyInitializer extends BasicLazyInitializer implements
persistentClass,
interfaces,
getIdentifier(),
( getSession() != null && getSession().isOpen() ? isReadOnly() : false ),
getIdentifierMethod,
setIdentifierMethod,
componentIdType

View File

@ -28,6 +28,7 @@ import java.io.Serializable;
import java.lang.reflect.Method;
import org.hibernate.HibernateException;
import org.hibernate.proxy.HibernateProxy;
import org.hibernate.type.AbstractComponentType;
/**
@ -39,6 +40,7 @@ public final class SerializableProxy implements Serializable {
private Class persistentClass;
private Class[] interfaces;
private Serializable id;
private boolean readOnly;
private Class getIdentifierMethodClass;
private Class setIdentifierMethodClass;
private String getIdentifierMethodName;
@ -53,6 +55,7 @@ public final class SerializableProxy implements Serializable {
final Class persistentClass,
final Class[] interfaces,
final Serializable id,
final boolean readOnly,
final Method getIdentifierMethod,
final Method setIdentifierMethod,
AbstractComponentType componentIdType
@ -61,6 +64,7 @@ public final class SerializableProxy implements Serializable {
this.persistentClass = persistentClass;
this.interfaces = interfaces;
this.id = id;
this.readOnly = readOnly;
if (getIdentifierMethod!=null) {
getIdentifierMethodClass = getIdentifierMethod.getDeclaringClass();
getIdentifierMethodName = getIdentifierMethod.getName();

View File

@ -229,6 +229,7 @@ public class JavassistLazyInitializer extends BasicLazyInitializer implements Me
persistentClass,
interfaces,
getIdentifier(),
( getSession() != null && getSession().isOpen() ? isReadOnly() : false ),
getIdentifierMethod,
setIdentifierMethod,
componentIdType

View File

@ -28,6 +28,7 @@ import java.io.Serializable;
import java.lang.reflect.Method;
import org.hibernate.HibernateException;
import org.hibernate.proxy.HibernateProxy;
import org.hibernate.type.AbstractComponentType;
/**
@ -39,6 +40,7 @@ public final class SerializableProxy implements Serializable {
private Class persistentClass;
private Class[] interfaces;
private Serializable id;
private boolean readOnly;
private Class getIdentifierMethodClass;
private Class setIdentifierMethodClass;
private String getIdentifierMethodName;
@ -53,6 +55,7 @@ public final class SerializableProxy implements Serializable {
final Class persistentClass,
final Class[] interfaces,
final Serializable id,
final boolean readOnly,
final Method getIdentifierMethod,
final Method setIdentifierMethod,
AbstractComponentType componentIdType
@ -61,6 +64,7 @@ public final class SerializableProxy implements Serializable {
this.persistentClass = persistentClass;
this.interfaces = interfaces;
this.id = id;
this.readOnly = readOnly;
if (getIdentifierMethod!=null) {
getIdentifierMethodClass = getIdentifierMethod.getDeclaringClass();
getIdentifierMethodName = getIdentifierMethod.getName();

View File

@ -29,6 +29,7 @@ import java.util.Iterator;
import junit.framework.Test;
import org.hibernate.Hibernate;
import org.hibernate.HibernateException;
import org.hibernate.Session;
import org.hibernate.Transaction;
@ -53,7 +54,234 @@ public class ImmutableTest extends FunctionalTestCase {
return new FunctionalTestClassTestSuite( ImmutableTest.class );
}
public void testPersistImmutable() {
Contract c = new Contract("gavin", "phone");
ContractVariation cv1 = new ContractVariation(1, c);
cv1.setText("expensive");
ContractVariation cv2 = new ContractVariation(2, c);
cv2.setText("more expensive");
Session s = openSession();
Transaction t = s.beginTransaction();
s.persist(c);
// c, cv1, and cv2 were added to s by s.persist(c) (not hibernate), so they are modifiable
assertFalse( s.isReadOnly( c ) );
assertFalse( s.isReadOnly( cv1 ) );
assertFalse( s.isReadOnly( cv2 ) );
t.commit();
s.close();
s = openSession();
t = s.beginTransaction();
c = (Contract) s.createCriteria(Contract.class).uniqueResult();
// c was loaded into s by hibernate, so it should be read-only
assertTrue( s.isReadOnly( c ) );
assertEquals( c.getCustomerName(), "gavin" );
assertEquals( c.getVariations().size(), 2 );
Iterator it = c.getVariations().iterator();
cv1 = (ContractVariation) it.next();
assertEquals( cv1.getText(), "expensive" );
cv2 = (ContractVariation) it.next();
assertEquals( cv2.getText(), "more expensive" );
// cv1 and cv2 were loaded into s by hibernate, so they should be read-only
assertTrue( s.isReadOnly( cv1 ) );
assertTrue( s.isReadOnly( cv2 ) );
s.delete(c);
assertEquals( s.createCriteria(Contract.class).setProjection( Projections.rowCount() ).uniqueResult(), new Long(0) );
assertEquals( s.createCriteria(ContractVariation.class).setProjection( Projections.rowCount() ).uniqueResult(), new Long(0) );
t.commit();
s.close();
}
public void testSaveImmutable() {
Contract c = new Contract("gavin", "phone");
ContractVariation cv1 = new ContractVariation(1, c);
cv1.setText("expensive");
ContractVariation cv2 = new ContractVariation(2, c);
cv2.setText("more expensive");
Session s = openSession();
Transaction t = s.beginTransaction();
s.save(c);
// c, cv1, and cv2 were added to s by s.persist(c) (not hibernate), so they are modifiable
assertFalse( s.isReadOnly( c ) );
assertFalse( s.isReadOnly( cv1 ) );
assertFalse( s.isReadOnly( cv2 ) );
t.commit();
s.close();
s = openSession();
t = s.beginTransaction();
c = (Contract) s.createCriteria(Contract.class).uniqueResult();
// c was loaded into s by hibernate, so it should be read-only
assertTrue( s.isReadOnly( c ) );
assertEquals( c.getCustomerName(), "gavin" );
assertEquals( c.getVariations().size(), 2 );
Iterator it = c.getVariations().iterator();
cv1 = (ContractVariation) it.next();
assertEquals( cv1.getText(), "expensive" );
cv2 = (ContractVariation) it.next();
assertEquals( cv2.getText(), "more expensive" );
// cv1 and cv2 were loaded into s by hibernate, so they should be read-only
assertTrue( s.isReadOnly( cv1 ) );
assertTrue( s.isReadOnly( cv2 ) );
s.delete(c);
assertEquals( s.createCriteria(Contract.class).setProjection( Projections.rowCount() ).uniqueResult(), new Long(0) );
assertEquals( s.createCriteria(ContractVariation.class).setProjection( Projections.rowCount() ).uniqueResult(), new Long(0) );
t.commit();
s.close();
}
public void testSaveOrUpdateImmutable() {
Contract c = new Contract("gavin", "phone");
ContractVariation cv1 = new ContractVariation(1, c);
cv1.setText("expensive");
ContractVariation cv2 = new ContractVariation(2, c);
cv2.setText("more expensive");
Session s = openSession();
Transaction t = s.beginTransaction();
s.saveOrUpdate(c);
// c, cv1, and cv2 were added to s by s.persist(c) (not hibernate), so they are modifiable
assertFalse( s.isReadOnly( c ) );
assertFalse( s.isReadOnly( cv1 ) );
assertFalse( s.isReadOnly( cv2 ) );
t.commit();
s.close();
s = openSession();
t = s.beginTransaction();
c = (Contract) s.createCriteria(Contract.class).uniqueResult();
// c was loaded into s by hibernate, so it should be read-only
assertTrue( s.isReadOnly( c ) );
assertEquals( c.getCustomerName(), "gavin" );
assertEquals( c.getVariations().size(), 2 );
Iterator it = c.getVariations().iterator();
cv1 = (ContractVariation) it.next();
assertEquals( cv1.getText(), "expensive" );
cv2 = (ContractVariation) it.next();
assertEquals( cv2.getText(), "more expensive" );
// cv1 and cv2 were loaded into s by hibernate, so they should be read-only
assertTrue( s.isReadOnly( cv1 ) );
assertTrue( s.isReadOnly( cv2 ) );
s.delete(c);
assertEquals( s.createCriteria(Contract.class).setProjection( Projections.rowCount() ).uniqueResult(), new Long(0) );
assertEquals( s.createCriteria(ContractVariation.class).setProjection( Projections.rowCount() ).uniqueResult(), new Long(0) );
t.commit();
s.close();
}
public void testImmutable() {
Contract c = new Contract("gavin", "phone");
ContractVariation cv1 = new ContractVariation(1, c);
cv1.setText("expensive");
ContractVariation cv2 = new ContractVariation(2, c);
cv2.setText("more expensive");
Session s = openSession();
Transaction t = s.beginTransaction();
s.persist(c);
// c, cv1, and cv2 were added to s by s.persist(c) (not hibernate), so they are modifiable
assertFalse( s.isReadOnly( c ) );
assertFalse( s.isReadOnly( cv1 ) );
assertFalse( s.isReadOnly( cv2 ) );
t.commit();
s.close();
s = openSession();
t = s.beginTransaction();
c = (Contract) s.createCriteria(Contract.class).uniqueResult();
// c was loaded into s, so it should be read-only
assertTrue( s.isReadOnly( c ) );
c.setCustomerName("foo bar");
c.getVariations().add( new ContractVariation(3, c) );
cv1 = (ContractVariation) c.getVariations().iterator().next();
cv1.setText("blah blah");
// cv1 and cv2 were loaded into s by hibernate, so they should be read-only
assertTrue( s.isReadOnly( cv1 ) );
assertFalse( s.contains( cv2 ) );
t.commit();
assertTrue( s.isReadOnly( c ) );
assertTrue( s.isReadOnly( cv1 ) );
assertFalse( s.contains( cv2 ) );
s.close();
s = openSession();
t = s.beginTransaction();
c = (Contract) s.createCriteria(Contract.class).uniqueResult();
// c was loaded into s by hibernate, so it should be read-only
assertTrue( s.isReadOnly( c ) );
assertEquals( c.getCustomerName(), "gavin" );
assertEquals( c.getVariations().size(), 2 );
Iterator it = c.getVariations().iterator();
cv1 = (ContractVariation) it.next();
assertEquals( cv1.getText(), "expensive" );
cv2 = (ContractVariation) it.next();
assertEquals( cv2.getText(), "more expensive" );
// cv1 and cv2 were loaded into s by hibernate, so they should be read-only
assertTrue( s.isReadOnly( cv1 ) );
assertTrue( s.isReadOnly( cv2 ) );
s.delete(c);
assertEquals( s.createCriteria(Contract.class).setProjection( Projections.rowCount() ).uniqueResult(), new Long(0) );
assertEquals( s.createCriteria(ContractVariation.class).setProjection( Projections.rowCount() ).uniqueResult(), new Long(0) );
t.commit();
s.close();
}
public void testPersistAndUpdateImmutable() {
Contract c = new Contract("gavin", "phone");
ContractVariation cv1 = new ContractVariation(1, c);
cv1.setText("expensive");
ContractVariation cv2 = new ContractVariation(2, c);
cv2.setText("more expensive");
Session s = openSession();
Transaction t = s.beginTransaction();
s.persist(c);
// c, cv1, and cv2 were added to s by s.persist(c) (not hibernate), so they are modifiable
assertFalse( s.isReadOnly( c ) );
assertFalse( s.isReadOnly( cv1 ) );
assertFalse( s.isReadOnly( cv2 ) );
c.setCustomerName( "Sherman" );
t.commit();
s.close();
s = openSession();
t = s.beginTransaction();
c = (Contract) s.createCriteria(Contract.class).uniqueResult();
// c was loaded into s, so it should be read-only
assertTrue( s.isReadOnly( c ) );
c.setCustomerName("foo bar");
c.getVariations().add( new ContractVariation(3, c) );
cv1 = (ContractVariation) c.getVariations().iterator().next();
cv1.setText("blah blah");
// cv1 and cv2 were loaded into s by hibernate, so they should be read-only
assertTrue( s.isReadOnly( cv1 ) );
assertFalse( s.contains( cv2 ) );
t.commit();
assertTrue( s.isReadOnly( c ) );
assertTrue( s.isReadOnly( cv1 ) );
assertFalse( s.contains( cv2 ) );
s.close();
s = openSession();
t = s.beginTransaction();
c = (Contract) s.createCriteria(Contract.class).uniqueResult();
// c was loaded into s by hibernate, so it should be read-only
assertTrue( s.isReadOnly( c ) );
assertEquals( c.getCustomerName(), "gavin" );
assertEquals( c.getVariations().size(), 2 );
Iterator it = c.getVariations().iterator();
cv1 = (ContractVariation) it.next();
assertEquals( cv1.getText(), "expensive" );
cv2 = (ContractVariation) it.next();
assertEquals( cv2.getText(), "more expensive" );
// cv1 and cv2 were loaded into s by hibernate, so they should be read-only
assertTrue( s.isReadOnly( cv1 ) );
assertTrue( s.isReadOnly( cv2 ) );
s.delete(c);
assertEquals( s.createCriteria(Contract.class).setProjection( Projections.rowCount() ).uniqueResult(), new Long(0) );
assertEquals( s.createCriteria(ContractVariation.class).setProjection( Projections.rowCount() ).uniqueResult(), new Long(0) );
t.commit();
s.close();
}
public void testUpdateAndDeleteManagedImmutable() {
Contract c = new Contract("gavin", "phone");
ContractVariation cv1 = new ContractVariation(1, c);
cv1.setText("expensive");
@ -68,16 +296,8 @@ public class ImmutableTest extends FunctionalTestCase {
s = openSession();
t = s.beginTransaction();
c = (Contract) s.createCriteria(Contract.class).uniqueResult();
c.setCustomerName("foo bar");
c.getVariations().add( new ContractVariation(3, c) );
cv1 = (ContractVariation) c.getVariations().iterator().next();
cv1.setText("blah blah");
t.commit();
s.close();
s = openSession();
t = s.beginTransaction();
c = (Contract) s.createCriteria(Contract.class).uniqueResult();
// c was loaded into s by hibernate, so it should be read-only
assertTrue( s.isReadOnly( c ) );
assertEquals( c.getCustomerName(), "gavin" );
assertEquals( c.getVariations().size(), 2 );
Iterator it = c.getVariations().iterator();
@ -85,6 +305,10 @@ public class ImmutableTest extends FunctionalTestCase {
assertEquals( cv1.getText(), "expensive" );
cv2 = (ContractVariation) it.next();
assertEquals( cv2.getText(), "more expensive" );
// cv1 and cv2 were loaded into s by hibernate, so they should be read-only
assertTrue( s.isReadOnly( cv1 ) );
assertTrue( s.isReadOnly( cv2 ) );
c.setCustomerName( "Sherman" );
s.delete(c);
assertEquals( s.createCriteria(Contract.class).setProjection( Projections.rowCount() ).uniqueResult(), new Long(0) );
assertEquals( s.createCriteria(ContractVariation.class).setProjection( Projections.rowCount() ).uniqueResult(), new Long(0) );
@ -92,6 +316,117 @@ public class ImmutableTest extends FunctionalTestCase {
s.close();
}
public void testGetAndDeleteManagedImmutable() {
Contract c = new Contract("gavin", "phone");
ContractVariation cv1 = new ContractVariation(1, c);
cv1.setText("expensive");
ContractVariation cv2 = new ContractVariation(2, c);
cv2.setText("more expensive");
Session s = openSession();
Transaction t = s.beginTransaction();
s.persist(c);
t.commit();
s.close();
s = openSession();
t = s.beginTransaction();
c = (Contract) s.get( Contract.class, c.getId() );
// c was loaded into s by hibernate, so it should be read-only
assertTrue( s.isReadOnly( c ) );
assertEquals( c.getCustomerName(), "gavin" );
assertEquals( c.getVariations().size(), 2 );
Iterator it = c.getVariations().iterator();
cv1 = (ContractVariation) it.next();
assertEquals( cv1.getText(), "expensive" );
cv2 = (ContractVariation) it.next();
assertEquals( cv2.getText(), "more expensive" );
// cv1 and cv2 were loaded into s by hibernate, so they should be read-only
assertTrue( s.isReadOnly( cv1 ) );
assertTrue( s.isReadOnly( cv2 ) );
c.setCustomerName( "Sherman" );
s.delete(c);
assertEquals( s.createCriteria(Contract.class).setProjection( Projections.rowCount() ).uniqueResult(), new Long(0) );
assertEquals( s.createCriteria(ContractVariation.class).setProjection( Projections.rowCount() ).uniqueResult(), new Long(0) );
t.commit();
s.close();
}
public void testDeleteDetachedImmutable() {
Contract c = new Contract("gavin", "phone");
ContractVariation cv1 = new ContractVariation(1, c);
cv1.setText("expensive");
ContractVariation cv2 = new ContractVariation(2, c);
cv2.setText("more expensive");
Session s = openSession();
Transaction t = s.beginTransaction();
s.persist(c);
t.commit();
s.close();
s = openSession();
t = s.beginTransaction();
s.delete( c );
/*
c = (Contract) s.createCriteria(Contract.class).uniqueResult();
// c was loaded into s by hibernate, so it should be read-only
assertTrue( s.isReadOnly( c ) );
assertEquals( c.getCustomerName(), "gavin" );
assertEquals( c.getVariations().size(), 2 );
Iterator it = c.getVariations().iterator();
cv1 = (ContractVariation) it.next();
assertEquals( cv1.getText(), "expensive" );
cv2 = (ContractVariation) it.next();
assertEquals( cv2.getText(), "more expensive" );
// cv1 and cv2 were loaded into s by hibernate, so they should be read-only
assertTrue( s.isReadOnly( cv1 ) );
assertTrue( s.isReadOnly( cv2 ) );
s.delete(c);
assertEquals( s.createCriteria(Contract.class).setProjection( Projections.rowCount() ).uniqueResult(), new Long(0) );
assertEquals( s.createCriteria(ContractVariation.class).setProjection( Projections.rowCount() ).uniqueResult(), new Long(0) );
*/
t.commit();
s.close();
}
public void testDeleteDetachedModifiedImmutable() {
Contract c = new Contract("gavin", "phone");
ContractVariation cv1 = new ContractVariation(1, c);
cv1.setText("expensive");
ContractVariation cv2 = new ContractVariation(2, c);
cv2.setText("more expensive");
Session s = openSession();
Transaction t = s.beginTransaction();
s.persist(c);
t.commit();
s.close();
s = openSession();
t = s.beginTransaction();
c.setCustomerName( "sherman" );
s.delete( c );
/*
c = (Contract) s.createCriteria(Contract.class).uniqueResult();
// c was loaded into s by hibernate, so it should be read-only
assertTrue( s.isReadOnly( c ) );
assertEquals( c.getCustomerName(), "gavin" );
assertEquals( c.getVariations().size(), 2 );
Iterator it = c.getVariations().iterator();
cv1 = (ContractVariation) it.next();
assertEquals( cv1.getText(), "expensive" );
cv2 = (ContractVariation) it.next();
assertEquals( cv2.getText(), "more expensive" );
// cv1 and cv2 were loaded into s by hibernate, so they should be read-only
assertTrue( s.isReadOnly( cv1 ) );
assertTrue( s.isReadOnly( cv2 ) );
s.delete(c);
assertEquals( s.createCriteria(Contract.class).setProjection( Projections.rowCount() ).uniqueResult(), new Long(0) );
assertEquals( s.createCriteria(ContractVariation.class).setProjection( Projections.rowCount() ).uniqueResult(), new Long(0) );
*/
t.commit();
s.close();
}
public void testImmutableParentEntityWithUpdate() {
Contract c = new Contract("gavin", "phone");
ContractVariation cv1 = new ContractVariation(1, c);
@ -108,7 +443,15 @@ public class ImmutableTest extends FunctionalTestCase {
t = s.beginTransaction();
c.setCustomerName("foo bar");
s.update( c );
// c was not loaded into s by hibernate, so it should be modifiable
assertFalse( s.isReadOnly( c ) );
assertFalse( s.contains( cv1 ) );
assertFalse( s.contains( cv2 ) );
t.commit();
// c, cv1, and cv2 were not loaded into s by hibernate, so they are modifiable
assertFalse( s.isReadOnly( c ) );
assertFalse( s.isReadOnly( cv1 ) );
assertFalse( s.isReadOnly( cv2 ) );
s.close();
s = openSession();
@ -145,7 +488,14 @@ public class ImmutableTest extends FunctionalTestCase {
cv1 = (ContractVariation) c.getVariations().iterator().next();
cv1.setText("blah blah");
s.update( c );
// c was not loaded into s by hibernate, so it should be modifiable
assertFalse( s.isReadOnly( c ) );
assertFalse( s.contains( cv1 ) );
assertFalse( s.contains( cv2 ) );
t.commit();
assertFalse( s.isReadOnly( c ) );
assertFalse( s.isReadOnly( cv1 ) );
assertFalse( s.isReadOnly( cv2 ) );
s.close();
s = openSession();
@ -224,7 +574,16 @@ public class ImmutableTest extends FunctionalTestCase {
s = openSession();
t = s.beginTransaction();
c.setCustomerName("foo bar");
s.merge( c );
c = ( Contract ) s.merge( c );
// c was loaded into s by hibernate in the merge process, so it is read-only
assertTrue( s.isReadOnly( c ) );
assertTrue( Hibernate.isInitialized( c.getVariations() ) );
Iterator it = c.getVariations().iterator();
cv1 = (ContractVariation) it.next();
cv2 = (ContractVariation) it.next();
// cv1 and cv2 were loaded into s by hibernate in the merge process, so they are read-only
assertTrue( s.isReadOnly( c ) );
assertTrue( s.isReadOnly( c ) );
t.commit();
s.close();
@ -233,7 +592,7 @@ public class ImmutableTest extends FunctionalTestCase {
c = (Contract) s.createCriteria(Contract.class).uniqueResult();
assertEquals( c.getCustomerName(), "gavin" );
assertEquals( c.getVariations().size(), 2 );
Iterator it = c.getVariations().iterator();
it = c.getVariations().iterator();
cv1 = (ContractVariation) it.next();
assertEquals( cv1.getText(), "expensive" );
cv2 = (ContractVariation) it.next();
@ -261,7 +620,16 @@ public class ImmutableTest extends FunctionalTestCase {
t = s.beginTransaction();
cv1 = (ContractVariation) c.getVariations().iterator().next();
cv1.setText("blah blah");
s.merge( c );
c = ( Contract ) s.merge( c );
// c was loaded into s by hibernate in the merge process, so it is read-only
assertTrue( s.isReadOnly( c ) );
assertTrue( Hibernate.isInitialized( c.getVariations() ) );
Iterator it = c.getVariations().iterator();
cv1 = (ContractVariation) it.next();
cv2 = (ContractVariation) it.next();
// cv1 and cv2 were loaded into s by hibernate in the merge process, so they are read-only
assertTrue( s.isReadOnly( c ) );
assertTrue( s.isReadOnly( c ) );
t.commit();
s.close();
@ -270,7 +638,7 @@ public class ImmutableTest extends FunctionalTestCase {
c = (Contract) s.createCriteria(Contract.class).uniqueResult();
assertEquals( c.getCustomerName(), "gavin" );
assertEquals( c.getVariations().size(), 2 );
Iterator it = c.getVariations().iterator();
it = c.getVariations().iterator();
cv1 = (ContractVariation) it.next();
assertEquals( cv1.getText(), "expensive" );
cv2 = (ContractVariation) it.next();

View File

@ -1,6 +1,9 @@
//$Id: GetLoadTest.java 10977 2006-12-12 23:28:04Z steve.ebersole@jboss.com $
package org.hibernate.test.nonflushedchanges;
import java.util.Iterator;
import java.util.List;
import junit.framework.Test;
import org.hibernate.Hibernate;
@ -8,6 +11,7 @@ import org.hibernate.Session;
import org.hibernate.cfg.Configuration;
import org.hibernate.cfg.Environment;
import org.hibernate.junit.functional.FunctionalTestClassTestSuite;
import org.hibernate.proxy.HibernateProxy;
import org.hibernate.test.tm.SimpleJtaTransactionManagerImpl;
@ -92,6 +96,131 @@ public class GetLoadTest extends AbstractOperationTestCase {
SimpleJtaTransactionManagerImpl.getInstance().commit();
assertFetchCount( 0 );
SimpleJtaTransactionManagerImpl.getInstance().begin();
s = openSession();
s.createQuery( "delete from Employer" ).executeUpdate();
List list = s.createQuery( "from Node" ).list();
for ( Iterator it=list.iterator(); it.hasNext(); ) {
s.delete( it.next() );
}
SimpleJtaTransactionManagerImpl.getInstance().commit();
}
public void testGetReadOnly() throws Exception {
clearCounts();
SimpleJtaTransactionManagerImpl.getInstance().begin();
Session s = openSession();
Employer emp = new Employer();
s.persist( emp );
Node node = new Node( "foo" );
Node parent = new Node( "bar" );
parent.addChild( node );
s.persist( parent );
SimpleJtaTransactionManagerImpl.getInstance().commit();
SimpleJtaTransactionManagerImpl.getInstance().begin();
s = openSession();
assertFalse( s.isDefaultReadOnly() );
s.setDefaultReadOnly( true );
emp = ( Employer ) s.get( Employer.class, emp.getId() );
assertTrue( s.isDefaultReadOnly() );
s = applyNonFlushedChangesToNewSessionCloseOldSession( s );
assertTrue( s.isDefaultReadOnly() );
emp = ( Employer ) getOldToNewEntityRefMap().get( emp );
assertTrue( Hibernate.isInitialized( emp ) );
assertFalse( Hibernate.isInitialized( emp.getEmployees() ) );
node = ( Node ) s.get( Node.class, node.getName() );
assertTrue( s.isReadOnly( emp ) );
assertTrue( s.isReadOnly( node ) );
s.setDefaultReadOnly( false );
s = applyNonFlushedChangesToNewSessionCloseOldSession( s );
assertFalse( s.isDefaultReadOnly() );
node = ( Node ) getOldToNewEntityRefMap().get( node );
emp = ( Employer ) getOldToNewEntityRefMap().get( emp );
assertTrue( Hibernate.isInitialized( node ) );
assertTrue( s.isReadOnly( node ) );
assertFalse( Hibernate.isInitialized( node.getParent() ) );
assertTrue( s.isReadOnly( emp ) );
assertFalse( Hibernate.isInitialized( node.getChildren() ) );
Hibernate.initialize( node.getChildren() );
for ( Iterator it=node.getChildren().iterator(); it.hasNext(); ) {
assertFalse( s.isReadOnly( it.next() ) );
}
assertFalse( Hibernate.isInitialized( node.getParent() ) );
assertNull( s.get( Node.class, "xyz" ) );
SimpleJtaTransactionManagerImpl.getInstance().commit();
SimpleJtaTransactionManagerImpl.getInstance().begin();
s = openSession();
assertFalse( s.isDefaultReadOnly() );
emp = ( Employer ) s.get( "org.hibernate.test.nonflushedchanges.Employer", emp.getId() );
s = applyNonFlushedChangesToNewSessionCloseOldSession( s );
assertFalse( s.isDefaultReadOnly() );
emp = ( Employer ) getOldToNewEntityRefMap().get( emp );
assertTrue( Hibernate.isInitialized( emp ) );
assertFalse( s.isReadOnly( emp ) );
s.setReadOnly( emp, true );
node = ( Node ) s.get( "org.hibernate.test.nonflushedchanges.Node", node.getName() );
assertFalse( s.isReadOnly( node ) );
s.setReadOnly( node, true );
s = applyNonFlushedChangesToNewSessionCloseOldSession( s );
emp = ( Employer ) getOldToNewEntityRefMap().get( emp );
assertTrue( s.isReadOnly( emp ) );
node = ( Node ) getOldToNewEntityRefMap().get( node );
assertTrue( Hibernate.isInitialized( node ) );
assertTrue( s.isReadOnly( node ) );
SimpleJtaTransactionManagerImpl.getInstance().commit();
assertFetchCount( 0 );
SimpleJtaTransactionManagerImpl.getInstance().begin();
s = openSession();
s.createQuery( "delete from Employer" ).executeUpdate();
List list = s.createQuery( "from Node" ).list();
for ( Iterator it=list.iterator(); it.hasNext(); ) {
s.delete( it.next() );
}
SimpleJtaTransactionManagerImpl.getInstance().commit();
}
public void testLoadReadOnlyFailureExpected() throws Exception {
clearCounts();
SimpleJtaTransactionManagerImpl.getInstance().begin();
Session s = openSession();
Employer emp = new Employer();
s.persist( emp );
Node node = new Node( "foo" );
Node parent = new Node( "bar" );
parent.addChild( node );
s.persist( parent );
SimpleJtaTransactionManagerImpl.getInstance().commit();
SimpleJtaTransactionManagerImpl.getInstance().begin();
s = openSession();
assertFalse( s.isDefaultReadOnly() );
s.setDefaultReadOnly( true );
emp = ( Employer ) s.load( Employer.class, emp.getId() );
assertFalse( Hibernate.isInitialized( emp ) );
assertTrue( s.isReadOnly( emp ) );
assertTrue( s.isDefaultReadOnly() );
s = applyNonFlushedChangesToNewSessionCloseOldSession( s );
assertTrue( s.isDefaultReadOnly() );
emp = ( Employer ) getOldToNewEntityRefMap().get( emp );
assertFalse( Hibernate.isInitialized( emp ) );
assertTrue( s.isReadOnly( emp ) );
SimpleJtaTransactionManagerImpl.getInstance().commit();
SimpleJtaTransactionManagerImpl.getInstance().begin();
s = openSession();
s.createQuery( "delete from Employer" ).executeUpdate();
List list = s.createQuery( "from Node" ).list();
for ( Iterator it=list.iterator(); it.hasNext(); ) {
s.delete( it.next() );
}
SimpleJtaTransactionManagerImpl.getInstance().commit();
}
public void testGetAfterDelete() throws Exception {

View File

@ -0,0 +1,117 @@
package org.hibernate.test.readonly;
import java.util.Set;
import java.util.HashSet;
import java.io.Serializable;
/**
* @author Steve Ebersole, Gail Badner (adapted this from "proxy" tests version)
*/
public class Container implements Serializable {
private Long id;
private String name;
private Owner noProxyOwner;
private Owner proxyOwner;
private Owner nonLazyOwner;
private Info noProxyInfo;
private Info proxyInfo;
private Info nonLazyInfo;
private Set lazyDataPoints = new HashSet();
private Set nonLazyJoinDataPoints = new HashSet();
private Set nonLazySelectDataPoints = new HashSet();
public Container() {
}
public Container(String name) {
this.name = name;
}
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Owner getNoProxyOwner() {
return noProxyOwner;
}
public void setNoProxyOwner(Owner noProxyOwner) {
this.noProxyOwner = noProxyOwner;
}
public Owner getProxyOwner() {
return proxyOwner;
}
public void setProxyOwner(Owner proxyOwner) {
this.proxyOwner = proxyOwner;
}
public Owner getNonLazyOwner() {
return nonLazyOwner;
}
public void setNonLazyOwner(Owner nonLazyOwner) {
this.nonLazyOwner = nonLazyOwner;
}
public Info getNoProxyInfo() {
return noProxyInfo;
}
public void setNoProxyInfo(Info noProxyInfo) {
this.noProxyInfo = noProxyInfo;
}
public Info getProxyInfo() {
return proxyInfo;
}
public void setProxyInfo(Info proxyInfo) {
this.proxyInfo = proxyInfo;
}
public Info getNonLazyInfo() {
return nonLazyInfo;
}
public void setNonLazyInfo(Info nonLazyInfo) {
this.nonLazyInfo = nonLazyInfo;
}
public Set getLazyDataPoints() {
return lazyDataPoints;
}
public void setLazyDataPoints(Set lazyDataPoints) {
this.lazyDataPoints = lazyDataPoints;
}
public Set getNonLazyJoinDataPoints() {
return nonLazyJoinDataPoints;
}
public void setNonLazyJoinDataPoints(Set nonLazyJoinDataPoints) {
this.nonLazyJoinDataPoints = nonLazyJoinDataPoints;
}
public Set getNonLazySelectDataPoints() {
return nonLazySelectDataPoints;
}
public void setNonLazySelectDataPoints(Set nonLazySelectDataPoints) {
this.nonLazySelectDataPoints = nonLazySelectDataPoints;
}
}

View File

@ -21,4 +21,43 @@
<property name="description"/>
</class>
<class name="Owner">
<id name="id">
<generator class="increment"/>
</id>
<property name="name" unique="true"/>
</class>
<class name="Info">
<id name="id">
<generator class="increment"/>
</id>
<property name="details"/>
</class>
<class name="Container">
<id name="id">
<generator class="increment"/>
</id>
<property name="name"/>
<many-to-one name="noProxyOwner" class="Owner" column="no_proxy_owner_name" property-ref="name" lazy="no-proxy" cascade="all"/>
<many-to-one name="proxyOwner" class="Owner" column="proxy_owner_name" property-ref="name" lazy="proxy" cascade="all"/>
<many-to-one name="nonLazyOwner" class="Owner" column="non_lazy_owner_name" property-ref="name" lazy="false" cascade="all"/>
<many-to-one name="noProxyInfo" class="Info" column="no_proxy_info_id" lazy="no-proxy" cascade="all"/>
<many-to-one name="proxyInfo" class="Info" column="proxy_info_id" lazy="proxy" cascade="all"/>
<many-to-one name="nonLazyInfo" class="Info" column="non_lazy_info_id" lazy="false" cascade="all"/>
<set name="lazyDataPoints" lazy="true" inverse="false" cascade="all">
<key column="c_lazy_id"/>
<one-to-many class="DataPoint"/>
</set>
<set name="nonLazySelectDataPoints" lazy="false" inverse="false" cascade="all" fetch="select">
<key column="c_non_lazy_select_id"/>
<one-to-many class="DataPoint"/>
</set>
<set name="nonLazyJoinDataPoints" lazy="false" inverse="false" cascade="all" fetch="join">
<key column="c_non_lazy_join_id"/>
<one-to-many class="DataPoint"/>
</set>
</class>
</hibernate-mapping>

View File

@ -2,15 +2,25 @@
package org.hibernate.test.readonly;
import java.math.BigDecimal;
import java.io.Serializable;
/**
* @author Gavin King
*/
public class DataPoint {
public class DataPoint implements Serializable {
private long id;
private BigDecimal x;
private BigDecimal y;
private String description;
public DataPoint() {}
public DataPoint(BigDecimal x, BigDecimal y, String description) {
this.x = x;
this.y = y;
this.description = description;
}
/**
* @return Returns the description.
*/
@ -59,4 +69,7 @@ public class DataPoint {
public void setY(BigDecimal y) {
this.y = y;
}
void exception() throws Exception {
throw new Exception("foo");
}
}

View File

@ -0,0 +1,34 @@
package org.hibernate.test.readonly;
/**
* todo: describe Info
*
* @author Steve Ebersole, Gail Badner (adapted this from "proxy" tests version)
*/
public class Info {
private Long id;
private String details;
public Info() {
}
public Info(String details) {
this.details = details;
}
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public String getDetails() {
return details;
}
public void setDetails(String details) {
this.details = details;
}
}

View File

@ -0,0 +1,34 @@
package org.hibernate.test.readonly;
import java.io.Serializable;
/**
* @author Steve Ebersole, Gail Badner (adapted this from "proxy" tests version)
*/
public class Owner implements Serializable {
private Long id;
private String name;
public Owner() {
}
public Owner(String name) {
this.name = name;
}
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}

View File

@ -0,0 +1,456 @@
//$Id: ReadOnlyTest.java 10977 2006-12-12 23:28:04Z steve.ebersole@jboss.com $
/*
* Hibernate, Relational Persistence for Idiomatic Java
*
* Copyright (c) 2008, 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.test.readonly;
import java.math.BigDecimal;
import java.util.List;
import junit.framework.Test;
import org.hibernate.CacheMode;
import org.hibernate.Hibernate;
import org.hibernate.ScrollMode;
import org.hibernate.ScrollableResults;
import org.hibernate.Session;
import org.hibernate.Transaction;
import org.hibernate.cfg.Configuration;
import org.hibernate.cfg.Environment;
import org.hibernate.junit.functional.FunctionalTestCase;
import org.hibernate.junit.functional.FunctionalTestClassTestSuite;
/**
*
* @author Gail Badner
*/
public class ReadOnlySessionTest extends FunctionalTestCase {
public ReadOnlySessionTest(String str) {
super(str);
}
public String[] getMappings() {
return new String[] { "readonly/DataPoint.hbm.xml", "readonly/TextHolder.hbm.xml" };
}
public void configure(Configuration cfg) {
cfg.setProperty(Environment.STATEMENT_BATCH_SIZE, "20");
}
public String getCacheConcurrencyStrategy() {
return null;
}
public static Test suite() {
return new FunctionalTestClassTestSuite( ReadOnlySessionTest.class );
}
public void testReadOnlyOnProxies() {
Session s = openSession();
s.setCacheMode( CacheMode.IGNORE );
s.beginTransaction();
DataPoint dp = new DataPoint();
dp.setX( new BigDecimal( 0.1d ).setScale(19, BigDecimal.ROUND_DOWN) );
dp.setY( new BigDecimal( Math.cos( dp.getX().doubleValue() ) ).setScale(19, BigDecimal.ROUND_DOWN) );
dp.setDescription( "original" );
s.save( dp );
long dpId = dp.getId();
s.getTransaction().commit();
s.close();
s = openSession();
s.setCacheMode(CacheMode.IGNORE);
s.beginTransaction();
s.setDefaultReadOnly( true );
assertTrue( s.isDefaultReadOnly() );
dp = ( DataPoint ) s.load( DataPoint.class, new Long( dpId ) );
s.setDefaultReadOnly( false );
assertFalse( "was initialized", Hibernate.isInitialized( dp ) );
assertTrue( s.isReadOnly( dp ) );
assertFalse( "was initialized during isReadOnly", Hibernate.isInitialized( dp ) );
dp.setDescription( "changed" );
assertTrue( "was not initialized during mod", Hibernate.isInitialized( dp ) );
assertEquals( "desc not changed in memory", "changed", dp.getDescription() );
s.flush();
s.getTransaction().commit();
s.close();
s = openSession();
s.beginTransaction();
List list = s.createQuery( "from DataPoint where description = 'changed'" ).list();
assertEquals( "change written to database", 0, list.size() );
s.createQuery("delete from DataPoint").executeUpdate();
s.getTransaction().commit();
s.close();
}
public void testReadOnlyMode() {
Session s = openSession();
s.setCacheMode(CacheMode.IGNORE);
Transaction t = s.beginTransaction();
for ( int i=0; i<100; i++ ) {
DataPoint dp = new DataPoint();
dp.setX( new BigDecimal(i * 0.1d).setScale(19, BigDecimal.ROUND_DOWN) );
dp.setY( new BigDecimal( Math.cos( dp.getX().doubleValue() ) ).setScale(19, BigDecimal.ROUND_DOWN) );
s.save(dp);
}
t.commit();
s.close();
s = openSession();
s.setCacheMode(CacheMode.IGNORE);
t = s.beginTransaction();
s.setDefaultReadOnly( true );
int i = 0;
ScrollableResults sr = s.createQuery("from DataPoint dp order by dp.x asc")
.scroll(ScrollMode.FORWARD_ONLY);
while ( sr.next() ) {
DataPoint dp = (DataPoint) sr.get(0);
if (++i==50) {
s.setReadOnly(dp, false);
}
dp.setDescription("done!");
}
t.commit();
s.clear();
t = s.beginTransaction();
List single = s.createQuery("from DataPoint where description='done!'").list();
assertEquals( single.size(), 1 );
s.createQuery("delete from DataPoint").executeUpdate();
t.commit();
s.close();
}
public void testReadOnlyQueryScrollChangeToModifiableBeforeIterate() {
Session s = openSession();
s.setCacheMode(CacheMode.IGNORE);
Transaction t = s.beginTransaction();
for ( int i=0; i<100; i++ ) {
DataPoint dp = new DataPoint();
dp.setX( new BigDecimal(i * 0.1d).setScale(19, BigDecimal.ROUND_DOWN) );
dp.setY( new BigDecimal( Math.cos( dp.getX().doubleValue() ) ).setScale(19, BigDecimal.ROUND_DOWN) );
s.save(dp);
}
t.commit();
s.close();
s = openSession();
s.setCacheMode(CacheMode.IGNORE);
t = s.beginTransaction();
s.setDefaultReadOnly( true );
int i = 0;
ScrollableResults sr = s.createQuery("from DataPoint dp order by dp.x asc")
.scroll(ScrollMode.FORWARD_ONLY);
s.setDefaultReadOnly( false );
while ( sr.next() ) {
DataPoint dp = (DataPoint) sr.get(0);
if (++i==50) {
s.setReadOnly(dp, false);
}
dp.setDescription("done!");
}
t.commit();
s.clear();
t = s.beginTransaction();
List single = s.createQuery("from DataPoint where description='done!'").list();
assertEquals( 1, single.size() );
s.createQuery("delete from DataPoint").executeUpdate();
t.commit();
s.close();
}
public void testReadOnlyRefreshFailureExpected() {
Session s = openSession();
s.setCacheMode(CacheMode.IGNORE);
Transaction t = s.beginTransaction();
DataPoint dp = new DataPoint();
dp.setDescription( "original" );
dp.setX( new BigDecimal(0.1d).setScale(19, BigDecimal.ROUND_DOWN) );
dp.setY( new BigDecimal( Math.cos( dp.getX().doubleValue() ) ).setScale(19, BigDecimal.ROUND_DOWN) );
s.save(dp);
t.commit();
s.close();
s = openSession();
s.setCacheMode(CacheMode.IGNORE);
s.setDefaultReadOnly( true );
t = s.beginTransaction();
dp = ( DataPoint ) s.get( DataPoint.class, dp.getId() );
assertEquals( "original", dp.getDescription() );
dp.setDescription( "changed" );
assertEquals( "changed", dp.getDescription() );
s.setDefaultReadOnly( false );
s.refresh( dp );
assertEquals( "original", dp.getDescription() );
dp.setDescription( "changed" );
assertEquals( "changed", dp.getDescription() );
t.commit();
s.clear();
t = s.beginTransaction();
dp = ( DataPoint ) s.get( DataPoint.class, dp.getId() );
assertEquals( "original", dp.getDescription() );
s.delete( dp );
t.commit();
s.close();
}
public void testReadOnlyDelete() {
Session s = openSession();
s.setCacheMode(CacheMode.IGNORE);
Transaction t = s.beginTransaction();
DataPoint dp = new DataPoint();
dp.setX( new BigDecimal(0.1d).setScale(19, BigDecimal.ROUND_DOWN) );
dp.setY( new BigDecimal( Math.cos( dp.getX().doubleValue() ) ).setScale(19, BigDecimal.ROUND_DOWN) );
s.save(dp);
t.commit();
s.close();
s = openSession();
s.setDefaultReadOnly( true );
s.setCacheMode(CacheMode.IGNORE);
t = s.beginTransaction();
dp = ( DataPoint ) s.get( DataPoint.class, dp.getId() );
s.setDefaultReadOnly( false );
assertTrue( s.isReadOnly( dp ) );
s.delete( dp );
t.commit();
s.close();
s = openSession();
t = s.beginTransaction();
List list = s.createQuery("from DataPoint where id=" + dp.getId() ).list();
assertTrue( list.isEmpty() );
t.commit();
s.close();
}
public void testReadOnlyGetModifyAndDelete() {
Session s = openSession();
s.setCacheMode(CacheMode.IGNORE);
Transaction t = s.beginTransaction();
DataPoint dp = new DataPoint();
dp.setX( new BigDecimal(0.1d).setScale(19, BigDecimal.ROUND_DOWN) );
dp.setY( new BigDecimal( Math.cos( dp.getX().doubleValue() ) ).setScale(19, BigDecimal.ROUND_DOWN) );
s.save(dp);
t.commit();
s.close();
s = openSession();
s.setDefaultReadOnly( true );
s.setCacheMode(CacheMode.IGNORE);
t = s.beginTransaction();
dp = ( DataPoint ) s.get( DataPoint.class, dp.getId() );
s.setDefaultReadOnly( true );
dp.setDescription( "a DataPoint" );
s.delete( dp );
t.commit();
s.close();
s = openSession();
t = s.beginTransaction();
List list = s.createQuery("from DataPoint where id=" + dp.getId() ).list();
assertTrue( list.isEmpty() );
t.commit();
s.close();
}
public void testReadOnlyModeWithExistingModifiableEntity() {
Session s = openSession();
s.setCacheMode(CacheMode.IGNORE);
Transaction t = s.beginTransaction();
DataPoint dp = null;
for ( int i=0; i<100; i++ ) {
dp = new DataPoint();
dp.setX( new BigDecimal(i * 0.1d).setScale(19, BigDecimal.ROUND_DOWN) );
dp.setY( new BigDecimal( Math.cos( dp.getX().doubleValue() ) ).setScale(19, BigDecimal.ROUND_DOWN) );
s.save(dp);
}
t.commit();
s.close();
s = openSession();
s.setCacheMode(CacheMode.IGNORE);
t = s.beginTransaction();
DataPoint dpLast = ( DataPoint ) s.get( DataPoint.class, dp.getId() );
assertFalse( s.isReadOnly( dpLast ) );
s.setDefaultReadOnly( true );
int i = 0;
ScrollableResults sr = s.createQuery("from DataPoint dp order by dp.x asc")
.scroll(ScrollMode.FORWARD_ONLY);
s.setDefaultReadOnly( false );
int nExpectedChanges = 0;
while ( sr.next() ) {
dp = (DataPoint) sr.get(0);
if ( dp.getId() == dpLast.getId() ) {
//dpLast existed in the session before executing the read-only query
assertFalse( s.isReadOnly( dp ) );
}
else {
assertTrue( s.isReadOnly( dp ) );
}
if (++i==50) {
s.setReadOnly(dp, false);
nExpectedChanges = ( dp == dpLast ? 1 : 2 );
}
dp.setDescription("done!");
}
t.commit();
s.clear();
t = s.beginTransaction();
List list = s.createQuery("from DataPoint where description='done!'").list();
assertEquals( nExpectedChanges, list.size() );
s.createQuery("delete from DataPoint").executeUpdate();
t.commit();
s.close();
}
public void testModifiableModeWithExistingReadOnlyEntity() {
Session s = openSession();
s.setCacheMode(CacheMode.IGNORE);
Transaction t = s.beginTransaction();
DataPoint dp = null;
for ( int i=0; i<100; i++ ) {
dp = new DataPoint();
dp.setX( new BigDecimal(i * 0.1d).setScale(19, BigDecimal.ROUND_DOWN) );
dp.setY( new BigDecimal( Math.cos( dp.getX().doubleValue() ) ).setScale(19, BigDecimal.ROUND_DOWN) );
s.save(dp);
}
t.commit();
s.close();
s = openSession();
s.setCacheMode(CacheMode.IGNORE);
t = s.beginTransaction();
s.setDefaultReadOnly( true );
DataPoint dpLast = ( DataPoint ) s.get( DataPoint.class, dp.getId() );
assertTrue( s.isReadOnly( dpLast ) );
int i = 0;
ScrollableResults sr = s.createQuery("from DataPoint dp order by dp.x asc")
.setReadOnly(false)
.scroll(ScrollMode.FORWARD_ONLY);
int nExpectedChanges = 0;
while ( sr.next() ) {
dp = (DataPoint) sr.get(0);
if ( dp.getId() == dpLast.getId() ) {
//dpLast existed in the session before executing the read-only query
assertTrue( s.isReadOnly( dp ) );
}
else {
assertFalse( s.isReadOnly( dp ) );
}
if (++i==50) {
s.setReadOnly(dp, true);
nExpectedChanges = ( dp == dpLast ? 99 : 98 );
}
dp.setDescription("done!");
}
t.commit();
s.clear();
t = s.beginTransaction();
List list = s.createQuery("from DataPoint where description='done!'").list();
assertEquals( nExpectedChanges, list.size() );
s.createQuery("delete from DataPoint").executeUpdate();
t.commit();
s.close();
}
public void testReadOnlyOnTextType() {
final String origText = "some huge text string";
final String newText = "some even bigger text string";
Session s = openSession();
s.beginTransaction();
s.setCacheMode( CacheMode.IGNORE );
TextHolder holder = new TextHolder( origText );
s.save( holder );
Long id = holder.getId();
s.getTransaction().commit();
s.close();
s = openSession();
s.beginTransaction();
s.setDefaultReadOnly( true );
s.setCacheMode( CacheMode.IGNORE );
holder = ( TextHolder ) s.get( TextHolder.class, id );
s.setDefaultReadOnly( false );
holder.setTheText( newText );
s.flush();
s.getTransaction().commit();
s.close();
s = openSession();
s.beginTransaction();
holder = ( TextHolder ) s.get( TextHolder.class, id );
assertEquals( "change written to database", origText, holder.getTheText() );
s.delete( holder );
s.getTransaction().commit();
s.close();
}
public void testMergeWithReadOnlyEntity() {
Session s = openSession();
s.setCacheMode(CacheMode.IGNORE);
Transaction t = s.beginTransaction();
DataPoint dp = new DataPoint();
dp.setX( new BigDecimal(0.1d).setScale(19, BigDecimal.ROUND_DOWN) );
dp.setY( new BigDecimal( Math.cos( dp.getX().doubleValue() ) ).setScale(19, BigDecimal.ROUND_DOWN) );
s.save(dp);
t.commit();
s.close();
dp.setDescription( "description" );
s = openSession();
s.setCacheMode(CacheMode.IGNORE);
t = s.beginTransaction();
s.setDefaultReadOnly( true );
DataPoint dpManaged = ( DataPoint ) s.get( DataPoint.class, new Long( dp.getId() ) );
DataPoint dpMerged = ( DataPoint ) s.merge( dp );
assertSame( dpManaged, dpMerged );
t.commit();
s.close();
s = openSession();
t = s.beginTransaction();
dpManaged = ( DataPoint ) s.get( DataPoint.class, new Long( dp.getId() ) );
assertNull( dpManaged.getDescription() );
s.delete( dpManaged );
t.commit();
s.close();
}
}

View File

@ -26,6 +26,7 @@
package org.hibernate.test.readonly;
import java.math.BigDecimal;
import java.util.Iterator;
import java.util.List;
import junit.framework.Test;
@ -44,6 +45,7 @@ import org.hibernate.junit.functional.FunctionalTestClassTestSuite;
/**
*
* @author Gavin King
* @author Gail Badner
*/
public class ReadOnlyTest extends FunctionalTestCase {
@ -142,6 +144,31 @@ public class ReadOnlyTest extends FunctionalTestCase {
}
public void testReadOnlyModeAutoFlushOnQuery() {
Session s = openSession();
s.setCacheMode(CacheMode.IGNORE);
Transaction t = s.beginTransaction();
DataPoint dpFirst = null;
for ( int i=0; i<100; i++ ) {
DataPoint dp = new DataPoint();
dp.setX( new BigDecimal(i * 0.1d).setScale(19, BigDecimal.ROUND_DOWN) );
dp.setY( new BigDecimal( Math.cos( dp.getX().doubleValue() ) ).setScale(19, BigDecimal.ROUND_DOWN) );
s.save(dp);
}
ScrollableResults sr = s.createQuery("from DataPoint dp order by dp.x asc")
.setReadOnly(true)
.scroll(ScrollMode.FORWARD_ONLY);
while ( sr.next() ) {
DataPoint dp = (DataPoint) sr.get(0);
assertFalse( s.isReadOnly( dp ) );
s.delete( dp );
}
t.commit();
s.close();
}
public void testReadOnlyRefreshFailureExpected() {
Session s = openSession();
@ -209,6 +236,37 @@ public class ReadOnlyTest extends FunctionalTestCase {
}
public void testReadOnlyGetModifyAndDelete() {
Session s = openSession();
s.setCacheMode(CacheMode.IGNORE);
Transaction t = s.beginTransaction();
DataPoint dp = new DataPoint();
dp.setX( new BigDecimal(0.1d).setScale(19, BigDecimal.ROUND_DOWN) );
dp.setY( new BigDecimal( Math.cos( dp.getX().doubleValue() ) ).setScale(19, BigDecimal.ROUND_DOWN) );
s.save(dp);
t.commit();
s.close();
s = openSession();
s.setCacheMode(CacheMode.IGNORE);
t = s.beginTransaction();
dp = ( DataPoint ) s.get( DataPoint.class, dp.getId() );
s.setReadOnly( dp, true );
dp.setDescription( "a DataPoint" );
s.delete( dp );
t.commit();
s.close();
s = openSession();
t = s.beginTransaction();
List list = s.createQuery("from DataPoint where description='done!'").list();
assertTrue( list.isEmpty() );
t.commit();
s.close();
}
public void testReadOnlyModeWithExistingModifiableEntity() {
Session s = openSession();