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:
parent
3b536fa6f6
commit
a0d8e6a415
|
@ -175,11 +175,46 @@ public interface Query {
|
||||||
public Query setFirstResult(int firstResult);
|
public Query setFirstResult(int firstResult);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Entities retrieved by this query will be loaded in
|
* Should entities and proxies loaded by this Query be put in read-only mode? If the
|
||||||
* a read-only mode where Hibernate will never dirty-check
|
* read-only/modifiable setting was not initialized, then the default
|
||||||
* them or make changes persistent.
|
* 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);
|
public Query setReadOnly(boolean readOnly);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -231,6 +231,44 @@ public interface Session extends Serializable {
|
||||||
*/
|
*/
|
||||||
public boolean isDirty() throws HibernateException;
|
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
|
* Return the identifier value of the given entity as associated with this
|
||||||
* session. An exception is thrown if the given entity instance is transient
|
* 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?
|
* 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
|
* @param entityOrProxy, an entity or HibernateProxy
|
||||||
* @return true, the entity or proxy is read-only;
|
* @return true, the entity or proxy is read-only;
|
||||||
* false, the entity or proxy is modifiable.
|
* 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
|
* 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
|
* object to modifiable mode. In read-only mode, no snapshot is maintained,
|
||||||
* and the instance is never dirty checked.
|
* the instance is never dirty checked, and changes are not persisted.
|
||||||
*
|
*
|
||||||
* If the entity or proxy already has the specified read-only/modifiable
|
* If the entity or proxy already has the specified read-only/modifiable
|
||||||
* setting, then this method does nothing.
|
* 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 entityOrProxy, an entity or HibernateProxy
|
||||||
* @param readOnly, if true, the entity or proxy is made read-only;
|
* @param readOnly, if true, the entity or proxy is made read-only;
|
||||||
* if false, the entity or proxy is made modifiable.
|
* if false, the entity or proxy is made modifiable.
|
||||||
* @see Query#setReadOnly(boolean)
|
|
||||||
*/
|
*/
|
||||||
public void setReadOnly(Object entityOrProxy, boolean readOnly);
|
public void setReadOnly(Object entityOrProxy, boolean readOnly);
|
||||||
|
|
||||||
|
|
|
@ -476,23 +476,92 @@ public interface PersistenceContext {
|
||||||
*/
|
*/
|
||||||
public boolean isPropertyNull(EntityKey ownerKey, String propertyName);
|
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?
|
* 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
|
* @param entityOrProxy
|
||||||
* @return true, the object is read-only; false, the object is modifiable.
|
* @return true, the object is read-only; false, the object is modifiable.
|
||||||
*/
|
*/
|
||||||
public boolean isReadOnly(Object entityOrProxy);
|
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
|
* If the entity or proxy already has the specified read-only/modifiable
|
||||||
* setting, then this method does nothing.
|
* 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 entityOrProxy, an entity or HibernateProxy
|
||||||
* @param readOnly, if true, the entity or proxy is made read-only;
|
* @param readOnly, if true, the entity or proxy is made read-only;
|
||||||
* if false, the entity or proxy is made modifiable.
|
* if false, the entity or proxy is made modifiable.
|
||||||
|
*
|
||||||
|
* @see org.hibernate.Session#setReadOnly(Object, boolean)
|
||||||
*/
|
*/
|
||||||
public void setReadOnly(Object entityOrProxy, boolean readOnly);
|
public void setReadOnly(Object entityOrProxy, boolean readOnly);
|
||||||
|
|
||||||
|
|
|
@ -66,6 +66,7 @@ public final class QueryParameters {
|
||||||
private Object optionalObject;
|
private Object optionalObject;
|
||||||
private String optionalEntityName;
|
private String optionalEntityName;
|
||||||
private Serializable optionalId;
|
private Serializable optionalId;
|
||||||
|
private boolean isReadOnlyInitialized;
|
||||||
private boolean readOnly;
|
private boolean readOnly;
|
||||||
private boolean callable = false;
|
private boolean callable = false;
|
||||||
private boolean autodiscovertypes = false;
|
private boolean autodiscovertypes = false;
|
||||||
|
@ -124,6 +125,7 @@ public final class QueryParameters {
|
||||||
null,
|
null,
|
||||||
false,
|
false,
|
||||||
false,
|
false,
|
||||||
|
false,
|
||||||
null,
|
null,
|
||||||
null,
|
null,
|
||||||
collectionKeys,
|
collectionKeys,
|
||||||
|
@ -149,6 +151,7 @@ public final class QueryParameters {
|
||||||
lockOptions,
|
lockOptions,
|
||||||
rowSelection,
|
rowSelection,
|
||||||
false,
|
false,
|
||||||
|
false,
|
||||||
cacheable,
|
cacheable,
|
||||||
cacheRegion,
|
cacheRegion,
|
||||||
comment,
|
comment,
|
||||||
|
@ -164,6 +167,7 @@ public final class QueryParameters {
|
||||||
final Map namedParameters,
|
final Map namedParameters,
|
||||||
final LockOptions lockOptions,
|
final LockOptions lockOptions,
|
||||||
final RowSelection rowSelection,
|
final RowSelection rowSelection,
|
||||||
|
final boolean isReadOnlyInitialized,
|
||||||
final boolean readOnly,
|
final boolean readOnly,
|
||||||
final boolean cacheable,
|
final boolean cacheable,
|
||||||
final String cacheRegion,
|
final String cacheRegion,
|
||||||
|
@ -181,6 +185,7 @@ public final class QueryParameters {
|
||||||
//this.forceCacheRefresh = forceCacheRefresh;
|
//this.forceCacheRefresh = forceCacheRefresh;
|
||||||
this.comment = comment;
|
this.comment = comment;
|
||||||
this.collectionKeys = collectionKeys;
|
this.collectionKeys = collectionKeys;
|
||||||
|
this.isReadOnlyInitialized = isReadOnlyInitialized;
|
||||||
this.readOnly = readOnly;
|
this.readOnly = readOnly;
|
||||||
this.resultTransformer = transformer;
|
this.resultTransformer = transformer;
|
||||||
}
|
}
|
||||||
|
@ -191,6 +196,7 @@ public final class QueryParameters {
|
||||||
final Map namedParameters,
|
final Map namedParameters,
|
||||||
final LockOptions lockOptions,
|
final LockOptions lockOptions,
|
||||||
final RowSelection rowSelection,
|
final RowSelection rowSelection,
|
||||||
|
final boolean isReadOnlyInitialized,
|
||||||
final boolean readOnly,
|
final boolean readOnly,
|
||||||
final boolean cacheable,
|
final boolean cacheable,
|
||||||
final String cacheRegion,
|
final String cacheRegion,
|
||||||
|
@ -207,6 +213,7 @@ public final class QueryParameters {
|
||||||
namedParameters,
|
namedParameters,
|
||||||
lockOptions,
|
lockOptions,
|
||||||
rowSelection,
|
rowSelection,
|
||||||
|
isReadOnlyInitialized,
|
||||||
readOnly,
|
readOnly,
|
||||||
cacheable,
|
cacheable,
|
||||||
cacheRegion,
|
cacheRegion,
|
||||||
|
@ -351,12 +358,82 @@ public final class QueryParameters {
|
||||||
this.optionalObject = optionalObject;
|
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() {
|
public boolean isReadOnly() {
|
||||||
|
if ( ! isReadOnlyInitialized() ) {
|
||||||
|
throw new IllegalStateException( "cannot call isReadOnly() when isReadOnlyInitialized() returns false" );
|
||||||
|
}
|
||||||
return readOnly;
|
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) {
|
public void setReadOnly(boolean readOnly) {
|
||||||
this.readOnly = readOnly;
|
this.readOnly = readOnly;
|
||||||
|
this.isReadOnlyInitialized = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setCallable(boolean callable) {
|
public void setCallable(boolean callable) {
|
||||||
|
@ -467,6 +544,7 @@ public final class QueryParameters {
|
||||||
this.namedParameters,
|
this.namedParameters,
|
||||||
this.lockOptions,
|
this.lockOptions,
|
||||||
selection,
|
selection,
|
||||||
|
this.isReadOnlyInitialized,
|
||||||
this.readOnly,
|
this.readOnly,
|
||||||
this.cacheable,
|
this.cacheable,
|
||||||
this.cacheRegion,
|
this.cacheRegion,
|
||||||
|
|
|
@ -127,6 +127,7 @@ public class StatefulPersistenceContext implements PersistenceContext {
|
||||||
private int loadCounter = 0;
|
private int loadCounter = 0;
|
||||||
private boolean flushing = false;
|
private boolean flushing = false;
|
||||||
|
|
||||||
|
private boolean defaultReadOnly = false;
|
||||||
private boolean hasNonReadOnlyEntities = false;
|
private boolean hasNonReadOnlyEntities = false;
|
||||||
|
|
||||||
private LoadContexts loadContexts;
|
private LoadContexts loadContexts;
|
||||||
|
@ -231,12 +232,27 @@ public class StatefulPersistenceContext implements PersistenceContext {
|
||||||
if ( batchFetchQueue != null ) {
|
if ( batchFetchQueue != null ) {
|
||||||
batchFetchQueue.clear();
|
batchFetchQueue.clear();
|
||||||
}
|
}
|
||||||
|
// defaultReadOnly is unaffected by clear()
|
||||||
hasNonReadOnlyEntities = false;
|
hasNonReadOnlyEntities = false;
|
||||||
if ( loadContexts != null ) {
|
if ( loadContexts != null ) {
|
||||||
loadContexts.cleanup();
|
loadContexts.cleanup();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@inheritDoc}
|
||||||
|
*/
|
||||||
|
public boolean isDefaultReadOnly() {
|
||||||
|
return defaultReadOnly;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@inheritDoc}
|
||||||
|
*/
|
||||||
|
public void setDefaultReadOnly(boolean defaultReadOnly) {
|
||||||
|
this.defaultReadOnly = defaultReadOnly;
|
||||||
|
}
|
||||||
|
|
||||||
public boolean hasNonReadOnlyEntities() {
|
public boolean hasNonReadOnlyEntities() {
|
||||||
return hasNonReadOnlyEntities;
|
return hasNonReadOnlyEntities;
|
||||||
}
|
}
|
||||||
|
@ -1396,6 +1412,7 @@ public class StatefulPersistenceContext implements PersistenceContext {
|
||||||
public void serialize(ObjectOutputStream oos) throws IOException {
|
public void serialize(ObjectOutputStream oos) throws IOException {
|
||||||
log.trace( "serializing persistent-context" );
|
log.trace( "serializing persistent-context" );
|
||||||
|
|
||||||
|
oos.writeBoolean( defaultReadOnly );
|
||||||
oos.writeBoolean( hasNonReadOnlyEntities );
|
oos.writeBoolean( hasNonReadOnlyEntities );
|
||||||
|
|
||||||
oos.writeInt( entitiesByKey.size() );
|
oos.writeInt( entitiesByKey.size() );
|
||||||
|
@ -1491,6 +1508,7 @@ public class StatefulPersistenceContext implements PersistenceContext {
|
||||||
// because serialization is used for different things.
|
// because serialization is used for different things.
|
||||||
|
|
||||||
try {
|
try {
|
||||||
|
rtn.defaultReadOnly = ois.readBoolean();
|
||||||
// todo : we can actually just determine this from the incoming EntityEntry-s
|
// todo : we can actually just determine this from the incoming EntityEntry-s
|
||||||
rtn.hasNonReadOnlyEntities = ois.readBoolean();
|
rtn.hasNonReadOnlyEntities = ois.readBoolean();
|
||||||
|
|
||||||
|
|
|
@ -298,6 +298,9 @@ 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;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -599,7 +602,10 @@ public class DefaultLoadEventListener extends AbstractLockUpgradeEventListener i
|
||||||
final PersistenceContext persistenceContext = session.getPersistenceContext();
|
final PersistenceContext persistenceContext = session.getPersistenceContext();
|
||||||
persistenceContext.addEntry(
|
persistenceContext.addEntry(
|
||||||
result,
|
result,
|
||||||
Status.MANAGED,
|
( session.isDefaultReadOnly() || ! persister.isMutable() ?
|
||||||
|
Status.READ_ONLY :
|
||||||
|
Status.MANAGED
|
||||||
|
),
|
||||||
values,
|
values,
|
||||||
null,
|
null,
|
||||||
id,
|
id,
|
||||||
|
|
|
@ -101,7 +101,7 @@ public abstract class AbstractQueryImpl implements Query {
|
||||||
private FlushMode sessionFlushMode;
|
private FlushMode sessionFlushMode;
|
||||||
private CacheMode sessionCacheMode;
|
private CacheMode sessionCacheMode;
|
||||||
private Serializable collectionKey;
|
private Serializable collectionKey;
|
||||||
private boolean readOnly;
|
private Boolean readOnly;
|
||||||
private ResultTransformer resultTransformer;
|
private ResultTransformer resultTransformer;
|
||||||
|
|
||||||
public AbstractQueryImpl(
|
public AbstractQueryImpl(
|
||||||
|
@ -202,12 +202,21 @@ public abstract class AbstractQueryImpl implements Query {
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@inheritDoc}
|
||||||
|
*/
|
||||||
public boolean isReadOnly() {
|
public boolean isReadOnly() {
|
||||||
return readOnly;
|
return ( readOnly == null ?
|
||||||
|
getSession().getPersistenceContext().isDefaultReadOnly() :
|
||||||
|
readOnly.booleanValue()
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@inheritDoc}
|
||||||
|
*/
|
||||||
public Query setReadOnly(boolean readOnly) {
|
public Query setReadOnly(boolean readOnly) {
|
||||||
this.readOnly = readOnly;
|
this.readOnly = Boolean.valueOf( readOnly );
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -881,7 +890,8 @@ public abstract class AbstractQueryImpl implements Query {
|
||||||
namedParams,
|
namedParams,
|
||||||
getLockOptions(),
|
getLockOptions(),
|
||||||
getSelection(),
|
getSelection(),
|
||||||
readOnly,
|
true,
|
||||||
|
isReadOnly(),
|
||||||
cacheable,
|
cacheable,
|
||||||
cacheRegion,
|
cacheRegion,
|
||||||
comment,
|
comment,
|
||||||
|
|
|
@ -1956,6 +1956,20 @@ public final class SessionImpl extends AbstractSessionImpl
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@inheritDoc}
|
||||||
|
*/
|
||||||
|
public boolean isDefaultReadOnly() {
|
||||||
|
return persistenceContext.isDefaultReadOnly();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@inheritDoc}
|
||||||
|
*/
|
||||||
|
public void setDefaultReadOnly(boolean defaultReadOnly) {
|
||||||
|
persistenceContext.setDefaultReadOnly( defaultReadOnly );
|
||||||
|
}
|
||||||
|
|
||||||
public boolean isReadOnly(Object entityOrProxy) {
|
public boolean isReadOnly(Object entityOrProxy) {
|
||||||
errorIfClosed();
|
errorIfClosed();
|
||||||
checkTransactionSynchStatus();
|
checkTransactionSynchStatus();
|
||||||
|
|
|
@ -483,6 +483,22 @@ public class StatelessSessionImpl extends AbstractSessionImpl
|
||||||
return false;
|
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!
|
//TODO: COPY/PASTE FROM SessionImpl, pull up!
|
||||||
|
|
|
@ -253,15 +253,32 @@ public abstract class Loader {
|
||||||
throws HibernateException, SQLException {
|
throws HibernateException, SQLException {
|
||||||
|
|
||||||
final PersistenceContext persistenceContext = session.getPersistenceContext();
|
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();
|
persistenceContext.beforeLoad();
|
||||||
List result;
|
List result;
|
||||||
try {
|
try {
|
||||||
result = doQuery( session, queryParameters, returnProxies );
|
try {
|
||||||
|
result = doQuery( session, queryParameters, returnProxies );
|
||||||
|
}
|
||||||
|
finally {
|
||||||
|
persistenceContext.afterLoad();
|
||||||
|
}
|
||||||
|
persistenceContext.initializeNonLazyCollections();
|
||||||
}
|
}
|
||||||
finally {
|
finally {
|
||||||
persistenceContext.afterLoad();
|
// Restore the original default
|
||||||
|
persistenceContext.setDefaultReadOnly( defaultReadOnlyOrig );
|
||||||
}
|
}
|
||||||
persistenceContext.initializeNonLazyCollections();
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -312,7 +329,7 @@ public abstract class Loader {
|
||||||
hydratedObjects,
|
hydratedObjects,
|
||||||
resultSet,
|
resultSet,
|
||||||
session,
|
session,
|
||||||
queryParameters.isReadOnly()
|
queryParameters.isReadOnly( session )
|
||||||
);
|
);
|
||||||
session.getPersistenceContext().initializeNonLazyCollections();
|
session.getPersistenceContext().initializeNonLazyCollections();
|
||||||
return result;
|
return result;
|
||||||
|
@ -363,7 +380,7 @@ public abstract class Loader {
|
||||||
hydratedObjects,
|
hydratedObjects,
|
||||||
resultSet,
|
resultSet,
|
||||||
session,
|
session,
|
||||||
queryParameters.isReadOnly()
|
queryParameters.isReadOnly( session )
|
||||||
);
|
);
|
||||||
session.getPersistenceContext().initializeNonLazyCollections();
|
session.getPersistenceContext().initializeNonLazyCollections();
|
||||||
return result;
|
return result;
|
||||||
|
@ -749,7 +766,7 @@ public abstract class Loader {
|
||||||
session.getBatcher().closeQueryStatement( st, rs );
|
session.getBatcher().closeQueryStatement( st, rs );
|
||||||
}
|
}
|
||||||
|
|
||||||
initializeEntitiesAndCollections( hydratedObjects, rs, session, queryParameters.isReadOnly() );
|
initializeEntitiesAndCollections( hydratedObjects, rs, session, queryParameters.isReadOnly( session ) );
|
||||||
|
|
||||||
if ( createSubselects ) createSubselects( subselectResultKeys, queryParameters, session );
|
if ( createSubselects ) createSubselects( subselectResultKeys, queryParameters, session );
|
||||||
|
|
||||||
|
@ -1884,7 +1901,7 @@ public abstract class Loader {
|
||||||
try {
|
try {
|
||||||
result = doQueryAndInitializeNonLazyCollections(
|
result = doQueryAndInitializeNonLazyCollections(
|
||||||
session,
|
session,
|
||||||
new QueryParameters(
|
new QueryParameters(
|
||||||
new Type[] { identifierType },
|
new Type[] { identifierType },
|
||||||
new Object[] { id },
|
new Object[] { id },
|
||||||
optionalObject,
|
optionalObject,
|
||||||
|
|
|
@ -65,11 +65,11 @@ 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...
|
// would be better to call unsetSession(), but it is not final...
|
||||||
session = null;
|
session = null;
|
||||||
readOnly = false;
|
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
setSession( session );
|
setSession( session );
|
||||||
|
@ -116,11 +116,11 @@ 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...
|
// would be better to call unsetSession(), but it is not final...
|
||||||
session = null;
|
session = null;
|
||||||
readOnly = false;
|
|
||||||
}
|
}
|
||||||
else if ( isConnectedToSession() ) {
|
else if ( isConnectedToSession() ) {
|
||||||
//TODO: perhaps this should be some other RuntimeException...
|
//TODO: perhaps this should be some other RuntimeException...
|
||||||
|
@ -128,8 +128,6 @@ public abstract class AbstractLazyInitializer implements LazyInitializer {
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
session = s;
|
session = s;
|
||||||
// NOTE: the proxy may not be connected to the session yet, so set readOnly directly
|
|
||||||
readOnly = ! session.getFactory().getEntityPersister( entityName ).isMutable();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -212,6 +212,7 @@ public final class CGLIBLazyInitializer extends BasicLazyInitializer implements
|
||||||
persistentClass,
|
persistentClass,
|
||||||
interfaces,
|
interfaces,
|
||||||
getIdentifier(),
|
getIdentifier(),
|
||||||
|
( getSession() != null && getSession().isOpen() ? isReadOnly() : false ),
|
||||||
getIdentifierMethod,
|
getIdentifierMethod,
|
||||||
setIdentifierMethod,
|
setIdentifierMethod,
|
||||||
componentIdType
|
componentIdType
|
||||||
|
|
|
@ -28,6 +28,7 @@ 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.HibernateProxy;
|
||||||
import org.hibernate.type.AbstractComponentType;
|
import org.hibernate.type.AbstractComponentType;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -39,6 +40,7 @@ public final class SerializableProxy implements Serializable {
|
||||||
private Class persistentClass;
|
private Class persistentClass;
|
||||||
private Class[] interfaces;
|
private Class[] interfaces;
|
||||||
private Serializable id;
|
private Serializable id;
|
||||||
|
private boolean readOnly;
|
||||||
private Class getIdentifierMethodClass;
|
private Class getIdentifierMethodClass;
|
||||||
private Class setIdentifierMethodClass;
|
private Class setIdentifierMethodClass;
|
||||||
private String getIdentifierMethodName;
|
private String getIdentifierMethodName;
|
||||||
|
@ -53,6 +55,7 @@ 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 Method getIdentifierMethod,
|
final Method getIdentifierMethod,
|
||||||
final Method setIdentifierMethod,
|
final Method setIdentifierMethod,
|
||||||
AbstractComponentType componentIdType
|
AbstractComponentType componentIdType
|
||||||
|
@ -61,6 +64,7 @@ public final class SerializableProxy implements Serializable {
|
||||||
this.persistentClass = persistentClass;
|
this.persistentClass = persistentClass;
|
||||||
this.interfaces = interfaces;
|
this.interfaces = interfaces;
|
||||||
this.id = id;
|
this.id = id;
|
||||||
|
this.readOnly = readOnly;
|
||||||
if (getIdentifierMethod!=null) {
|
if (getIdentifierMethod!=null) {
|
||||||
getIdentifierMethodClass = getIdentifierMethod.getDeclaringClass();
|
getIdentifierMethodClass = getIdentifierMethod.getDeclaringClass();
|
||||||
getIdentifierMethodName = getIdentifierMethod.getName();
|
getIdentifierMethodName = getIdentifierMethod.getName();
|
||||||
|
|
|
@ -229,6 +229,7 @@ public class JavassistLazyInitializer extends BasicLazyInitializer implements Me
|
||||||
persistentClass,
|
persistentClass,
|
||||||
interfaces,
|
interfaces,
|
||||||
getIdentifier(),
|
getIdentifier(),
|
||||||
|
( getSession() != null && getSession().isOpen() ? isReadOnly() : false ),
|
||||||
getIdentifierMethod,
|
getIdentifierMethod,
|
||||||
setIdentifierMethod,
|
setIdentifierMethod,
|
||||||
componentIdType
|
componentIdType
|
||||||
|
|
|
@ -28,6 +28,7 @@ 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.HibernateProxy;
|
||||||
import org.hibernate.type.AbstractComponentType;
|
import org.hibernate.type.AbstractComponentType;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -39,6 +40,7 @@ public final class SerializableProxy implements Serializable {
|
||||||
private Class persistentClass;
|
private Class persistentClass;
|
||||||
private Class[] interfaces;
|
private Class[] interfaces;
|
||||||
private Serializable id;
|
private Serializable id;
|
||||||
|
private boolean readOnly;
|
||||||
private Class getIdentifierMethodClass;
|
private Class getIdentifierMethodClass;
|
||||||
private Class setIdentifierMethodClass;
|
private Class setIdentifierMethodClass;
|
||||||
private String getIdentifierMethodName;
|
private String getIdentifierMethodName;
|
||||||
|
@ -53,6 +55,7 @@ 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 Method getIdentifierMethod,
|
final Method getIdentifierMethod,
|
||||||
final Method setIdentifierMethod,
|
final Method setIdentifierMethod,
|
||||||
AbstractComponentType componentIdType
|
AbstractComponentType componentIdType
|
||||||
|
@ -61,6 +64,7 @@ public final class SerializableProxy implements Serializable {
|
||||||
this.persistentClass = persistentClass;
|
this.persistentClass = persistentClass;
|
||||||
this.interfaces = interfaces;
|
this.interfaces = interfaces;
|
||||||
this.id = id;
|
this.id = id;
|
||||||
|
this.readOnly = readOnly;
|
||||||
if (getIdentifierMethod!=null) {
|
if (getIdentifierMethod!=null) {
|
||||||
getIdentifierMethodClass = getIdentifierMethod.getDeclaringClass();
|
getIdentifierMethodClass = getIdentifierMethod.getDeclaringClass();
|
||||||
getIdentifierMethodName = getIdentifierMethod.getName();
|
getIdentifierMethodName = getIdentifierMethod.getName();
|
||||||
|
|
|
@ -29,6 +29,7 @@ import java.util.Iterator;
|
||||||
|
|
||||||
import junit.framework.Test;
|
import junit.framework.Test;
|
||||||
|
|
||||||
|
import org.hibernate.Hibernate;
|
||||||
import org.hibernate.HibernateException;
|
import org.hibernate.HibernateException;
|
||||||
import org.hibernate.Session;
|
import org.hibernate.Session;
|
||||||
import org.hibernate.Transaction;
|
import org.hibernate.Transaction;
|
||||||
|
@ -53,7 +54,234 @@ public class ImmutableTest extends FunctionalTestCase {
|
||||||
return new FunctionalTestClassTestSuite( ImmutableTest.class );
|
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() {
|
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");
|
Contract c = new Contract("gavin", "phone");
|
||||||
ContractVariation cv1 = new ContractVariation(1, c);
|
ContractVariation cv1 = new ContractVariation(1, c);
|
||||||
cv1.setText("expensive");
|
cv1.setText("expensive");
|
||||||
|
@ -64,20 +292,12 @@ public class ImmutableTest extends FunctionalTestCase {
|
||||||
s.persist(c);
|
s.persist(c);
|
||||||
t.commit();
|
t.commit();
|
||||||
s.close();
|
s.close();
|
||||||
|
|
||||||
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();
|
s = openSession();
|
||||||
t = s.beginTransaction();
|
t = s.beginTransaction();
|
||||||
c = (Contract) s.createCriteria(Contract.class).uniqueResult();
|
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.getCustomerName(), "gavin" );
|
||||||
assertEquals( c.getVariations().size(), 2 );
|
assertEquals( c.getVariations().size(), 2 );
|
||||||
Iterator it = c.getVariations().iterator();
|
Iterator it = c.getVariations().iterator();
|
||||||
|
@ -85,6 +305,10 @@ public class ImmutableTest extends FunctionalTestCase {
|
||||||
assertEquals( cv1.getText(), "expensive" );
|
assertEquals( cv1.getText(), "expensive" );
|
||||||
cv2 = (ContractVariation) it.next();
|
cv2 = (ContractVariation) it.next();
|
||||||
assertEquals( cv2.getText(), "more expensive" );
|
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);
|
s.delete(c);
|
||||||
assertEquals( s.createCriteria(Contract.class).setProjection( Projections.rowCount() ).uniqueResult(), new Long(0) );
|
assertEquals( s.createCriteria(Contract.class).setProjection( Projections.rowCount() ).uniqueResult(), new Long(0) );
|
||||||
assertEquals( s.createCriteria(ContractVariation.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();
|
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() {
|
public void testImmutableParentEntityWithUpdate() {
|
||||||
Contract c = new Contract("gavin", "phone");
|
Contract c = new Contract("gavin", "phone");
|
||||||
ContractVariation cv1 = new ContractVariation(1, c);
|
ContractVariation cv1 = new ContractVariation(1, c);
|
||||||
|
@ -108,7 +443,15 @@ public class ImmutableTest extends FunctionalTestCase {
|
||||||
t = s.beginTransaction();
|
t = s.beginTransaction();
|
||||||
c.setCustomerName("foo bar");
|
c.setCustomerName("foo bar");
|
||||||
s.update( c );
|
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();
|
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.close();
|
||||||
|
|
||||||
s = openSession();
|
s = openSession();
|
||||||
|
@ -145,7 +488,14 @@ public class ImmutableTest extends FunctionalTestCase {
|
||||||
cv1 = (ContractVariation) c.getVariations().iterator().next();
|
cv1 = (ContractVariation) c.getVariations().iterator().next();
|
||||||
cv1.setText("blah blah");
|
cv1.setText("blah blah");
|
||||||
s.update( c );
|
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();
|
t.commit();
|
||||||
|
assertFalse( s.isReadOnly( c ) );
|
||||||
|
assertFalse( s.isReadOnly( cv1 ) );
|
||||||
|
assertFalse( s.isReadOnly( cv2 ) );
|
||||||
s.close();
|
s.close();
|
||||||
|
|
||||||
s = openSession();
|
s = openSession();
|
||||||
|
@ -224,7 +574,16 @@ public class ImmutableTest extends FunctionalTestCase {
|
||||||
s = openSession();
|
s = openSession();
|
||||||
t = s.beginTransaction();
|
t = s.beginTransaction();
|
||||||
c.setCustomerName("foo bar");
|
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();
|
t.commit();
|
||||||
s.close();
|
s.close();
|
||||||
|
|
||||||
|
@ -233,7 +592,7 @@ public class ImmutableTest extends FunctionalTestCase {
|
||||||
c = (Contract) s.createCriteria(Contract.class).uniqueResult();
|
c = (Contract) s.createCriteria(Contract.class).uniqueResult();
|
||||||
assertEquals( c.getCustomerName(), "gavin" );
|
assertEquals( c.getCustomerName(), "gavin" );
|
||||||
assertEquals( c.getVariations().size(), 2 );
|
assertEquals( c.getVariations().size(), 2 );
|
||||||
Iterator it = c.getVariations().iterator();
|
it = c.getVariations().iterator();
|
||||||
cv1 = (ContractVariation) it.next();
|
cv1 = (ContractVariation) it.next();
|
||||||
assertEquals( cv1.getText(), "expensive" );
|
assertEquals( cv1.getText(), "expensive" );
|
||||||
cv2 = (ContractVariation) it.next();
|
cv2 = (ContractVariation) it.next();
|
||||||
|
@ -261,7 +620,16 @@ public class ImmutableTest extends FunctionalTestCase {
|
||||||
t = s.beginTransaction();
|
t = s.beginTransaction();
|
||||||
cv1 = (ContractVariation) c.getVariations().iterator().next();
|
cv1 = (ContractVariation) c.getVariations().iterator().next();
|
||||||
cv1.setText("blah blah");
|
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();
|
t.commit();
|
||||||
s.close();
|
s.close();
|
||||||
|
|
||||||
|
@ -270,7 +638,7 @@ public class ImmutableTest extends FunctionalTestCase {
|
||||||
c = (Contract) s.createCriteria(Contract.class).uniqueResult();
|
c = (Contract) s.createCriteria(Contract.class).uniqueResult();
|
||||||
assertEquals( c.getCustomerName(), "gavin" );
|
assertEquals( c.getCustomerName(), "gavin" );
|
||||||
assertEquals( c.getVariations().size(), 2 );
|
assertEquals( c.getVariations().size(), 2 );
|
||||||
Iterator it = c.getVariations().iterator();
|
it = c.getVariations().iterator();
|
||||||
cv1 = (ContractVariation) it.next();
|
cv1 = (ContractVariation) it.next();
|
||||||
assertEquals( cv1.getText(), "expensive" );
|
assertEquals( cv1.getText(), "expensive" );
|
||||||
cv2 = (ContractVariation) it.next();
|
cv2 = (ContractVariation) it.next();
|
||||||
|
|
|
@ -1,6 +1,9 @@
|
||||||
//$Id: GetLoadTest.java 10977 2006-12-12 23:28:04Z steve.ebersole@jboss.com $
|
//$Id: GetLoadTest.java 10977 2006-12-12 23:28:04Z steve.ebersole@jboss.com $
|
||||||
package org.hibernate.test.nonflushedchanges;
|
package org.hibernate.test.nonflushedchanges;
|
||||||
|
|
||||||
|
import java.util.Iterator;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
import junit.framework.Test;
|
import junit.framework.Test;
|
||||||
|
|
||||||
import org.hibernate.Hibernate;
|
import org.hibernate.Hibernate;
|
||||||
|
@ -8,6 +11,7 @@ import org.hibernate.Session;
|
||||||
import org.hibernate.cfg.Configuration;
|
import org.hibernate.cfg.Configuration;
|
||||||
import org.hibernate.cfg.Environment;
|
import org.hibernate.cfg.Environment;
|
||||||
import org.hibernate.junit.functional.FunctionalTestClassTestSuite;
|
import org.hibernate.junit.functional.FunctionalTestClassTestSuite;
|
||||||
|
import org.hibernate.proxy.HibernateProxy;
|
||||||
import org.hibernate.test.tm.SimpleJtaTransactionManagerImpl;
|
import org.hibernate.test.tm.SimpleJtaTransactionManagerImpl;
|
||||||
|
|
||||||
|
|
||||||
|
@ -92,6 +96,131 @@ public class GetLoadTest extends AbstractOperationTestCase {
|
||||||
SimpleJtaTransactionManagerImpl.getInstance().commit();
|
SimpleJtaTransactionManagerImpl.getInstance().commit();
|
||||||
|
|
||||||
assertFetchCount( 0 );
|
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 {
|
public void testGetAfterDelete() throws Exception {
|
||||||
|
|
|
@ -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;
|
||||||
|
}
|
||||||
|
}
|
|
@ -21,4 +21,43 @@
|
||||||
<property name="description"/>
|
<property name="description"/>
|
||||||
</class>
|
</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>
|
</hibernate-mapping>
|
||||||
|
|
|
@ -2,15 +2,25 @@
|
||||||
package org.hibernate.test.readonly;
|
package org.hibernate.test.readonly;
|
||||||
|
|
||||||
import java.math.BigDecimal;
|
import java.math.BigDecimal;
|
||||||
|
import java.io.Serializable;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author Gavin King
|
* @author Gavin King
|
||||||
*/
|
*/
|
||||||
public class DataPoint {
|
public class DataPoint implements Serializable {
|
||||||
private long id;
|
private long id;
|
||||||
private BigDecimal x;
|
private BigDecimal x;
|
||||||
private BigDecimal y;
|
private BigDecimal y;
|
||||||
private String description;
|
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.
|
* @return Returns the description.
|
||||||
*/
|
*/
|
||||||
|
@ -59,4 +69,7 @@ public class DataPoint {
|
||||||
public void setY(BigDecimal y) {
|
public void setY(BigDecimal y) {
|
||||||
this.y = y;
|
this.y = y;
|
||||||
}
|
}
|
||||||
|
void exception() throws Exception {
|
||||||
|
throw new Exception("foo");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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;
|
||||||
|
}
|
||||||
|
}
|
|
@ -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;
|
||||||
|
}
|
||||||
|
}
|
File diff suppressed because it is too large
Load Diff
|
@ -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();
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
|
@ -26,6 +26,7 @@
|
||||||
package org.hibernate.test.readonly;
|
package org.hibernate.test.readonly;
|
||||||
|
|
||||||
import java.math.BigDecimal;
|
import java.math.BigDecimal;
|
||||||
|
import java.util.Iterator;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
import junit.framework.Test;
|
import junit.framework.Test;
|
||||||
|
@ -44,6 +45,7 @@ import org.hibernate.junit.functional.FunctionalTestClassTestSuite;
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
* @author Gavin King
|
* @author Gavin King
|
||||||
|
* @author Gail Badner
|
||||||
*/
|
*/
|
||||||
public class ReadOnlyTest extends FunctionalTestCase {
|
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() {
|
public void testReadOnlyRefreshFailureExpected() {
|
||||||
|
|
||||||
Session s = openSession();
|
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() {
|
public void testReadOnlyModeWithExistingModifiableEntity() {
|
||||||
|
|
||||||
Session s = openSession();
|
Session s = openSession();
|
||||||
|
|
Loading…
Reference in New Issue