diff --git a/core/src/main/java/org/hibernate/engine/EntityEntry.java b/core/src/main/java/org/hibernate/engine/EntityEntry.java
index 1c5b4ee819..b5d33ef1a2 100644
--- a/core/src/main/java/org/hibernate/engine/EntityEntry.java
+++ b/core/src/main/java/org/hibernate/engine/EntityEntry.java
@@ -46,6 +46,7 @@ public final class EntityEntry implements Serializable {
private LockMode lockMode;
private Status status;
+ private Status previousStatus;
private final Serializable id;
private Object[] loadedState;
private Object[] deletedState;
@@ -72,6 +73,7 @@ public final class EntityEntry implements Serializable {
final boolean disableVersionIncrement,
final boolean lazyPropertiesAreUnfetched) {
this.status=status;
+ this.previousStatus = null;
this.loadedState=loadedState;
this.id=id;
this.rowId=rowId;
@@ -91,6 +93,7 @@ public final class EntityEntry implements Serializable {
final Serializable id,
final EntityMode entityMode,
final Status status,
+ final Status previousStatus,
final Object[] loadedState,
final Object[] deletedState,
final Object version,
@@ -104,6 +107,7 @@ public final class EntityEntry implements Serializable {
this.id = id;
this.entityMode = entityMode;
this.status = status;
+ this.previousStatus = previousStatus;
this.loadedState = loadedState;
this.deletedState = deletedState;
this.version = version;
@@ -130,7 +134,10 @@ public final class EntityEntry implements Serializable {
if (status==Status.READ_ONLY) {
loadedState = null; //memory optimization
}
- this.status = status;
+ if ( this.status != status ) {
+ this.previousStatus = this.status;
+ this.status = status;
+ }
}
public Serializable getId() {
@@ -220,6 +227,7 @@ public final class EntityEntry implements Serializable {
* exists in the database
*/
public void postDelete() {
+ previousStatus = status;
status = Status.GONE;
existsInDatabase = false;
}
@@ -246,18 +254,29 @@ public final class EntityEntry implements Serializable {
return loadedState[propertyIndex];
}
- public boolean requiresDirtyCheck(Object entity) {
-
- boolean isMutableInstance =
- status != Status.READ_ONLY &&
- persister.isMutable();
-
- return isMutableInstance && (
+ public boolean requiresDirtyCheck(Object entity) {
+ return isModifiableEntity() && (
getPersister().hasMutableProperties() ||
!FieldInterceptionHelper.isInstrumented( entity ) ||
FieldInterceptionHelper.extractFieldInterceptor( entity).isDirty()
);
-
+ }
+
+ /**
+ * Can the entity be modified?
+ *
+ * The entity is modifiable if all of the following are true:
+ *
+ * - the entity class is mutable
+ * - the entity is not read-only
+ * - if the current status is Status.DELETED, then the entity was not read-only when it was deleted
+ *
+ * @return true, if the entity is modifiable; false, otherwise,
+ */
+ public boolean isModifiableEntity() {
+ return ( status != Status.READ_ONLY ) &&
+ ! ( status == Status.DELETED && previousStatus == Status.READ_ONLY ) &&
+ getPersister().isMutable();
}
public void forceLocked(Object entity, Object nextVersion) {
@@ -318,6 +337,7 @@ public final class EntityEntry implements Serializable {
oos.writeObject( id );
oos.writeObject( entityMode.toString() );
oos.writeObject( status.toString() );
+ oos.writeObject( ( previousStatus == null ? "" : previousStatus.toString() ) );
// todo : potentially look at optimizing these two arrays
oos.writeObject( loadedState );
oos.writeObject( deletedState );
@@ -344,12 +364,17 @@ public final class EntityEntry implements Serializable {
static EntityEntry deserialize(
ObjectInputStream ois,
SessionImplementor session) throws IOException, ClassNotFoundException {
+ String previousStatusString = null;
return new EntityEntry(
( session == null ? null : session.getFactory() ),
( String ) ois.readObject(),
( Serializable ) ois.readObject(),
EntityMode.parse( ( String ) ois.readObject() ),
Status.parse( ( String ) ois.readObject() ),
+ ( ( previousStatusString = ( String ) ois.readObject() ).length() == 0 ?
+ null :
+ Status.parse( previousStatusString )
+ ),
( Object[] ) ois.readObject(),
( Object[] ) ois.readObject(),
ois.readObject(),
diff --git a/core/src/main/java/org/hibernate/event/def/DefaultFlushEntityEventListener.java b/core/src/main/java/org/hibernate/event/def/DefaultFlushEntityEventListener.java
index 8a60da2bb0..0845569ef1 100755
--- a/core/src/main/java/org/hibernate/event/def/DefaultFlushEntityEventListener.java
+++ b/core/src/main/java/org/hibernate/event/def/DefaultFlushEntityEventListener.java
@@ -38,7 +38,6 @@ import org.hibernate.classic.Validatable;
import org.hibernate.engine.EntityEntry;
import org.hibernate.engine.EntityKey;
import org.hibernate.engine.Nullability;
-import org.hibernate.engine.SessionFactoryImplementor;
import org.hibernate.engine.SessionImplementor;
import org.hibernate.engine.Status;
import org.hibernate.engine.Versioning;
@@ -254,10 +253,24 @@ public class DefaultFlushEntityEventListener implements FlushEntityEventListener
if ( log.isTraceEnabled() ) {
if ( status == Status.DELETED ) {
- log.trace(
+ if ( ! persister.isMutable() ) {
+ log.trace(
+ "Updating immutable, deleted entity: " +
+ MessageHelper.infoString( persister, entry.getId(), session.getFactory() )
+ );
+ }
+ else if ( ! entry.isModifiableEntity() ) {
+ log.trace(
+ "Updating non-modifiable, deleted entity: " +
+ MessageHelper.infoString( persister, entry.getId(), session.getFactory() )
+ );
+ }
+ else {
+ log.trace(
"Updating deleted entity: " +
MessageHelper.infoString( persister, entry.getId(), session.getFactory() )
);
+ }
}
else {
log.trace(
@@ -303,7 +316,9 @@ public class DefaultFlushEntityEventListener implements FlushEntityEventListener
values,
dirtyProperties,
event.hasDirtyCollection(),
- entry.getLoadedState(),
+ ( status == Status.DELETED && ! entry.isModifiableEntity() ?
+ persister.getPropertyValues( entity, entityMode ) :
+ entry.getLoadedState() ),
entry.getVersion(),
nextVersion,
entity,
@@ -447,7 +462,7 @@ public class DefaultFlushEntityEventListener implements FlushEntityEventListener
}
private boolean hasDirtyCollections(FlushEntityEvent event, EntityPersister persister, Status status) {
- if ( isCollectionDirtyCheckNecessary(persister, status) ) {
+ if ( isCollectionDirtyCheckNecessary(persister, status ) ) {
DirtyCollectionSearchVisitor visitor = new DirtyCollectionSearchVisitor(
event.getSession(),
persister.getPropertyVersionability()
@@ -463,8 +478,8 @@ public class DefaultFlushEntityEventListener implements FlushEntityEventListener
}
private boolean isCollectionDirtyCheckNecessary(EntityPersister persister, Status status) {
- return status==Status.MANAGED &&
- persister.isVersioned() &&
+ return status==Status.MANAGED &&
+ persister.isVersioned() &&
persister.hasCollections();
}
@@ -503,7 +518,27 @@ public class DefaultFlushEntityEventListener implements FlushEntityEventListener
if ( !cannotDirtyCheck ) {
// dirty check against the usual snapshot of the entity
dirtyProperties = persister.findDirty( values, loadedState, entity, session );
-
+ }
+ else if ( entry.getStatus() == Status.DELETED && ! event.getEntityEntry().isModifiableEntity() ) {
+ // A non-modifiable (e.g., read-only or immutable) entity needs to be have
+ // references to transient entities set to null before being deleted. No other
+ // fields should be updated.
+ if ( values != entry.getDeletedState() ) {
+ throw new IllegalStateException(
+ "Entity has status Status.DELETED but values != entry.getDeletedState"
+ );
+ }
+ // Even if loadedState == null, we can dirty-check by comparing currentState and
+ // entry.getDeletedState() because the only fields to be updated are those that
+ // refer to transient entities that are being set to null.
+ // - currentState contains the entity's current property values.
+ // - entry.getDeletedState() contains the entity's current property values with
+ // references to transient entities set to null.
+ // - dirtyProperties will only contain properties that refer to transient entities
+ final Object[] currentState =
+ persister.getPropertyValues( event.getEntity(), event.getSession().getEntityMode() );
+ dirtyProperties = persister.findDirty( entry.getDeletedState(), currentState, entity, session );
+ cannotDirtyCheck = false;
}
else {
// dirty check against the database snapshot, if possible/necessary
diff --git a/core/src/main/java/org/hibernate/persister/entity/AbstractEntityPersister.java b/core/src/main/java/org/hibernate/persister/entity/AbstractEntityPersister.java
index e9a8e59ea4..f0a76d0d3c 100644
--- a/core/src/main/java/org/hibernate/persister/entity/AbstractEntityPersister.java
+++ b/core/src/main/java/org/hibernate/persister/entity/AbstractEntityPersister.java
@@ -63,6 +63,7 @@ import org.hibernate.engine.LoadQueryInfluencers;
import org.hibernate.engine.Mapping;
import org.hibernate.engine.SessionFactoryImplementor;
import org.hibernate.engine.SessionImplementor;
+import org.hibernate.engine.Status;
import org.hibernate.engine.ValueInclusion;
import org.hibernate.engine.Versioning;
import org.hibernate.exception.JDBCExceptionHelper;
@@ -2751,8 +2752,21 @@ public abstract class AbstractEntityPersister
final boolean[] propsToUpdate;
final String[] updateStrings;
- if ( entityMetamodel.isDynamicUpdate() && dirtyFields != null ) {
- // For the case of dynamic-update="true", we need to generate the UPDATE SQL
+ EntityEntry entry = session.getPersistenceContext().getEntry( object );
+
+ // Ensure that an immutable or non-modifiable entity is not being updated unless it is
+ // in the process of being deleted.
+ if ( entry == null && ! isMutable() ) {
+ throw new IllegalStateException( "Updating immutable entity that is not in session yet!" );
+ }
+ if ( entry != null && ! isModifiableEntity( entry ) && entry.getStatus() != Status.DELETED ) {
+ throw new IllegalStateException( "Updating non-modifiable entity that is not being deleted!" );
+ }
+ if ( ( entityMetamodel.isDynamicUpdate() || ! isModifiableEntity( entry ) ) && dirtyFields != null ) {
+ // For the following cases we need to generate the UPDATE SQL
+ // - dynamic-update="true"
+ // - a non-modifiable entity (e.g., read-only or immutable) needs to have
+ // references to transient entities set to null before being deleted
propsToUpdate = getPropertiesToUpdate( dirtyFields, hasDirtyCollection );
// don't need to check laziness (dirty checking algorithm handles that)
updateStrings = new String[span];
@@ -3595,6 +3609,11 @@ public abstract class AbstractEntityPersister
return entityMetamodel.isMutable();
}
+ private boolean isModifiableEntity(EntityEntry entry) {
+
+ return ( entry == null ? isMutable() : entry.isModifiableEntity() );
+ }
+
public boolean isAbstract() {
return entityMetamodel.isAbstract();
}
diff --git a/testsuite/src/test/java/org/hibernate/test/immutable/Contract.java b/testsuite/src/test/java/org/hibernate/test/immutable/Contract.java
index 1cd4bc5411..9dbf034689 100755
--- a/testsuite/src/test/java/org/hibernate/test/immutable/Contract.java
+++ b/testsuite/src/test/java/org/hibernate/test/immutable/Contract.java
@@ -3,7 +3,10 @@ package org.hibernate.test.immutable;
import java.io.Serializable;
import java.util.ArrayList;
+import java.util.HashSet;
+import java.util.Iterator;
import java.util.List;
+import java.util.Set;
public class Contract implements Serializable {
@@ -11,15 +14,36 @@ public class Contract implements Serializable {
private String customerName;
private String type;
private List variations;
+ private Contract parent;
+ private Set subcontracts;
+ private Set plans;
+ private Set parties;
+ private Set infos;
public Contract() {
super();
}
- public Contract(String customerName, String type) {
+ public Contract(Plan plan, String customerName, String type) {
+ plans = new HashSet();
+ plans.add( plan );
+ if ( plan != null ) {
+ plan.getContracts().add( this );
+ }
this.customerName = customerName;
this.type = type;
variations = new ArrayList();
+ subcontracts = new HashSet();
+ parties = new HashSet();
+ infos = new HashSet();
+ }
+
+ public Set getPlans() {
+ return plans;
+ }
+
+ public void setPlans(Set plans) {
+ this.plans = plans;
}
public String getCustomerName() {
@@ -54,4 +78,55 @@ public class Contract implements Serializable {
this.variations = variations;
}
+ public Contract getParent() {
+ return parent;
+ }
+
+ public void setParent(Contract parent) {
+ this.parent = parent;
+ }
+
+ public Set getSubcontracts() {
+ return subcontracts;
+ }
+
+ public void setSubcontracts(Set subcontracts) {
+ this.subcontracts = subcontracts;
+ }
+
+ public void addSubcontract(Contract subcontract) {
+ subcontracts.add( subcontract );
+ subcontract.setParent( this );
+ }
+
+ public Set getParties() {
+ return parties;
+ }
+
+ public void setParties(Set parties) {
+ this.parties = parties;
+ }
+
+ public void addParty(Party party) {
+ parties.add( party );
+ party.setContract( this );
+ }
+
+ public void removeParty(Party party) {
+ parties.remove( party );
+ party.setContract( null );
+ }
+
+ public Set getInfos() {
+ return infos;
+ }
+
+ public void setInfos(Set infos) {
+ this.infos = infos;
+ }
+
+ public void addInfo(Info info) {
+ infos.add( info );
+ info.setContract( this );
+ }
}
diff --git a/testsuite/src/test/java/org/hibernate/test/immutable/ContractVariation.hbm.xml b/testsuite/src/test/java/org/hibernate/test/immutable/ContractVariation.hbm.xml
index a117028b29..32a2c35d49 100755
--- a/testsuite/src/test/java/org/hibernate/test/immutable/ContractVariation.hbm.xml
+++ b/testsuite/src/test/java/org/hibernate/test/immutable/ContractVariation.hbm.xml
@@ -10,7 +10,34 @@
-->
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
@@ -22,8 +49,27 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
+
diff --git a/testsuite/src/test/java/org/hibernate/test/immutable/ImmutableTest.java b/testsuite/src/test/java/org/hibernate/test/immutable/ImmutableTest.java
index f9ea84847f..5ef8e55f04 100755
--- a/testsuite/src/test/java/org/hibernate/test/immutable/ImmutableTest.java
+++ b/testsuite/src/test/java/org/hibernate/test/immutable/ImmutableTest.java
@@ -33,6 +33,8 @@ import org.hibernate.Hibernate;
import org.hibernate.HibernateException;
import org.hibernate.Session;
import org.hibernate.Transaction;
+import org.hibernate.cfg.Configuration;
+import org.hibernate.cfg.Environment;
import org.hibernate.criterion.Projections;
import org.hibernate.junit.functional.FunctionalTestCase;
import org.hibernate.junit.functional.FunctionalTestClassTestSuite;
@@ -46,6 +48,11 @@ public class ImmutableTest extends FunctionalTestCase {
super(str);
}
+ public void configure(Configuration cfg) {
+ cfg.setProperty( Environment.GENERATE_STATISTICS, "true");
+ cfg.setProperty( Environment.STATEMENT_BATCH_SIZE, "0" );
+ }
+
public String[] getMappings() {
return new String[] { "immutable/ContractVariation.hbm.xml" };
}
@@ -55,11 +62,14 @@ public class ImmutableTest extends FunctionalTestCase {
}
public void testPersistImmutable() {
- Contract c = new Contract("gavin", "phone");
+ Contract c = new Contract( null, "gavin", "phone");
ContractVariation cv1 = new ContractVariation(1, c);
cv1.setText("expensive");
ContractVariation cv2 = new ContractVariation(2, c);
cv2.setText("more expensive");
+
+ clearCounts();
+
Session s = openSession();
Transaction t = s.beginTransaction();
s.persist(c);
@@ -70,6 +80,10 @@ public class ImmutableTest extends FunctionalTestCase {
t.commit();
s.close();
+ assertInsertCount( 3 );
+ assertUpdateCount( 0 );
+ clearCounts();
+
s = openSession();
t = s.beginTransaction();
c = (Contract) s.createCriteria(Contract.class).uniqueResult();
@@ -90,10 +104,64 @@ public class ImmutableTest extends FunctionalTestCase {
assertEquals( s.createCriteria(ContractVariation.class).setProjection( Projections.rowCount() ).uniqueResult(), new Long(0) );
t.commit();
s.close();
+
+ assertUpdateCount( 0 );
+ assertDeleteCount( 3 );
+ }
+
+ public void testPersistUpdateImmutableInSameTransaction() {
+ Contract c = new Contract( null, "gavin", "phone");
+ ContractVariation cv1 = new ContractVariation(1, c);
+ cv1.setText("expensive");
+ ContractVariation cv2 = new ContractVariation(2, c);
+ cv2.setText("more expensive");
+
+ clearCounts();
+
+ 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( "gail" );
+ t.commit();
+ s.close();
+
+ assertInsertCount( 3 );
+ assertUpdateCount( 0 );
+ clearCounts();
+
+ 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();
+
+ assertUpdateCount( 0 );
+ assertDeleteCount( 3 );
}
public void testSaveImmutable() {
- Contract c = new Contract("gavin", "phone");
+ clearCounts();
+
+ Contract c = new Contract( null, "gavin", "phone");
ContractVariation cv1 = new ContractVariation(1, c);
cv1.setText("expensive");
ContractVariation cv2 = new ContractVariation(2, c);
@@ -108,6 +176,10 @@ public class ImmutableTest extends FunctionalTestCase {
t.commit();
s.close();
+ assertInsertCount( 3 );
+ assertUpdateCount( 0 );
+ clearCounts();
+
s = openSession();
t = s.beginTransaction();
c = (Contract) s.createCriteria(Contract.class).uniqueResult();
@@ -128,10 +200,15 @@ public class ImmutableTest extends FunctionalTestCase {
assertEquals( s.createCriteria(ContractVariation.class).setProjection( Projections.rowCount() ).uniqueResult(), new Long(0) );
t.commit();
s.close();
+
+ assertUpdateCount( 0 );
+ assertDeleteCount( 3 );
}
public void testSaveOrUpdateImmutable() {
- Contract c = new Contract("gavin", "phone");
+ clearCounts();
+
+ Contract c = new Contract( null, "gavin", "phone");
ContractVariation cv1 = new ContractVariation(1, c);
cv1.setText("expensive");
ContractVariation cv2 = new ContractVariation(2, c);
@@ -146,6 +223,10 @@ public class ImmutableTest extends FunctionalTestCase {
t.commit();
s.close();
+ assertInsertCount( 3 );
+ assertUpdateCount( 0 );
+ clearCounts();
+
s = openSession();
t = s.beginTransaction();
c = (Contract) s.createCriteria(Contract.class).uniqueResult();
@@ -166,10 +247,15 @@ public class ImmutableTest extends FunctionalTestCase {
assertEquals( s.createCriteria(ContractVariation.class).setProjection( Projections.rowCount() ).uniqueResult(), new Long(0) );
t.commit();
s.close();
+
+ assertUpdateCount( 0 );
+ assertDeleteCount( 3 );
}
public void testImmutable() {
- Contract c = new Contract("gavin", "phone");
+ clearCounts();
+
+ Contract c = new Contract( null, "gavin", "phone");
ContractVariation cv1 = new ContractVariation(1, c);
cv1.setText("expensive");
ContractVariation cv2 = new ContractVariation(2, c);
@@ -183,7 +269,11 @@ public class ImmutableTest extends FunctionalTestCase {
assertFalse( s.isReadOnly( cv2 ) );
t.commit();
s.close();
-
+
+ assertInsertCount( 3 );
+ assertUpdateCount( 0 );
+ clearCounts();
+
s = openSession();
t = s.beginTransaction();
c = (Contract) s.createCriteria(Contract.class).uniqueResult();
@@ -201,7 +291,11 @@ public class ImmutableTest extends FunctionalTestCase {
assertTrue( s.isReadOnly( cv1 ) );
assertFalse( s.contains( cv2 ) );
s.close();
-
+
+ assertInsertCount( 0 );
+ assertUpdateCount( 0 );
+ clearCounts();
+
s = openSession();
t = s.beginTransaction();
c = (Contract) s.createCriteria(Contract.class).uniqueResult();
@@ -222,10 +316,15 @@ public class ImmutableTest extends FunctionalTestCase {
assertEquals( s.createCriteria(ContractVariation.class).setProjection( Projections.rowCount() ).uniqueResult(), new Long(0) );
t.commit();
s.close();
+
+ assertUpdateCount( 0 );
+ assertDeleteCount( 3 );
}
public void testPersistAndUpdateImmutable() {
- Contract c = new Contract("gavin", "phone");
+ clearCounts();
+
+ Contract c = new Contract( null, "gavin", "phone");
ContractVariation cv1 = new ContractVariation(1, c);
cv1.setText("expensive");
ContractVariation cv2 = new ContractVariation(2, c);
@@ -241,6 +340,10 @@ public class ImmutableTest extends FunctionalTestCase {
t.commit();
s.close();
+ assertInsertCount( 3 );
+ assertUpdateCount( 0 );
+ clearCounts();
+
s = openSession();
t = s.beginTransaction();
c = (Contract) s.createCriteria(Contract.class).uniqueResult();
@@ -259,6 +362,10 @@ public class ImmutableTest extends FunctionalTestCase {
assertFalse( s.contains( cv2 ) );
s.close();
+ assertInsertCount( 0 );
+ assertUpdateCount( 0 );
+ clearCounts();
+
s = openSession();
t = s.beginTransaction();
c = (Contract) s.createCriteria(Contract.class).uniqueResult();
@@ -279,10 +386,15 @@ public class ImmutableTest extends FunctionalTestCase {
assertEquals( s.createCriteria(ContractVariation.class).setProjection( Projections.rowCount() ).uniqueResult(), new Long(0) );
t.commit();
s.close();
+
+ assertUpdateCount( 0 );
+ assertDeleteCount( 3 );
}
public void testUpdateAndDeleteManagedImmutable() {
- Contract c = new Contract("gavin", "phone");
+ clearCounts();
+
+ Contract c = new Contract( null, "gavin", "phone");
ContractVariation cv1 = new ContractVariation(1, c);
cv1.setText("expensive");
ContractVariation cv2 = new ContractVariation(2, c);
@@ -293,6 +405,10 @@ public class ImmutableTest extends FunctionalTestCase {
t.commit();
s.close();
+ assertInsertCount( 3 );
+ assertUpdateCount( 0 );
+ clearCounts();
+
s = openSession();
t = s.beginTransaction();
c = (Contract) s.createCriteria(Contract.class).uniqueResult();
@@ -314,10 +430,15 @@ public class ImmutableTest extends FunctionalTestCase {
assertEquals( s.createCriteria(ContractVariation.class).setProjection( Projections.rowCount() ).uniqueResult(), new Long(0) );
t.commit();
s.close();
+
+ assertUpdateCount( 0 );
+ assertDeleteCount( 3 );
}
public void testGetAndDeleteManagedImmutable() {
- Contract c = new Contract("gavin", "phone");
+ clearCounts();
+
+ Contract c = new Contract( null, "gavin", "phone");
ContractVariation cv1 = new ContractVariation(1, c);
cv1.setText("expensive");
ContractVariation cv2 = new ContractVariation(2, c);
@@ -328,6 +449,10 @@ public class ImmutableTest extends FunctionalTestCase {
t.commit();
s.close();
+ assertInsertCount( 3 );
+ assertUpdateCount( 0 );
+ clearCounts();
+
s = openSession();
t = s.beginTransaction();
c = (Contract) s.get( Contract.class, c.getId() );
@@ -349,10 +474,15 @@ public class ImmutableTest extends FunctionalTestCase {
assertEquals( s.createCriteria(ContractVariation.class).setProjection( Projections.rowCount() ).uniqueResult(), new Long(0) );
t.commit();
s.close();
+
+ assertUpdateCount( 0 );
+ assertDeleteCount( 3 );
}
public void testDeleteDetachedImmutable() {
- Contract c = new Contract("gavin", "phone");
+ clearCounts();
+
+ Contract c = new Contract( null, "gavin", "phone");
ContractVariation cv1 = new ContractVariation(1, c);
cv1.setText("expensive");
ContractVariation cv2 = new ContractVariation(2, c);
@@ -363,33 +493,26 @@ public class ImmutableTest extends FunctionalTestCase {
t.commit();
s.close();
+ assertInsertCount( 3 );
+ assertUpdateCount( 0 );
+ clearCounts();
+
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) );
- */
+ assertNull( c );
t.commit();
s.close();
+
+ assertUpdateCount( 0 );
+ assertDeleteCount( 3 );
}
public void testDeleteDetachedModifiedImmutable() {
- Contract c = new Contract("gavin", "phone");
+ clearCounts();
+
+ Contract c = new Contract( null, "gavin", "phone");
ContractVariation cv1 = new ContractVariation(1, c);
cv1.setText("expensive");
ContractVariation cv2 = new ContractVariation(2, c);
@@ -400,35 +523,26 @@ public class ImmutableTest extends FunctionalTestCase {
t.commit();
s.close();
+ assertInsertCount( 3 );
+ assertUpdateCount( 0 );
+ clearCounts();
+
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();
+
+ assertUpdateCount( 0 );
+ assertDeleteCount( 3 );
}
public void testImmutableParentEntityWithUpdate() {
- Contract c = new Contract("gavin", "phone");
+ clearCounts();
+
+ Contract c = new Contract( null, "gavin", "phone");
ContractVariation cv1 = new ContractVariation(1, c);
cv1.setText("expensive");
ContractVariation cv2 = new ContractVariation(2, c);
@@ -439,6 +553,10 @@ public class ImmutableTest extends FunctionalTestCase {
t.commit();
s.close();
+ assertInsertCount( 3 );
+ assertUpdateCount( 0 );
+ clearCounts();
+
s = openSession();
t = s.beginTransaction();
c.setCustomerName("foo bar");
@@ -454,6 +572,8 @@ public class ImmutableTest extends FunctionalTestCase {
assertFalse( s.isReadOnly( cv2 ) );
s.close();
+ assertUpdateCount( 0 );
+
s = openSession();
t = s.beginTransaction();
c = (Contract) s.createCriteria(Contract.class).uniqueResult();
@@ -469,10 +589,15 @@ public class ImmutableTest extends FunctionalTestCase {
assertEquals( s.createCriteria(ContractVariation.class).setProjection( Projections.rowCount() ).uniqueResult(), new Long(0) );
t.commit();
s.close();
+
+ assertUpdateCount( 0 );
+ assertDeleteCount( 3 );
}
public void testImmutableChildEntityWithUpdate() {
- Contract c = new Contract("gavin", "phone");
+ clearCounts();
+
+ Contract c = new Contract( null, "gavin", "phone");
ContractVariation cv1 = new ContractVariation(1, c);
cv1.setText("expensive");
ContractVariation cv2 = new ContractVariation(2, c);
@@ -483,6 +608,10 @@ public class ImmutableTest extends FunctionalTestCase {
t.commit();
s.close();
+ assertInsertCount( 3 );
+ assertUpdateCount( 0 );
+ clearCounts();
+
s = openSession();
t = s.beginTransaction();
cv1 = (ContractVariation) c.getVariations().iterator().next();
@@ -498,6 +627,8 @@ public class ImmutableTest extends FunctionalTestCase {
assertFalse( s.isReadOnly( cv2 ) );
s.close();
+ assertUpdateCount( 0 );
+
s = openSession();
t = s.beginTransaction();
c = (Contract) s.createCriteria(Contract.class).uniqueResult();
@@ -513,10 +644,15 @@ public class ImmutableTest extends FunctionalTestCase {
assertEquals( s.createCriteria(ContractVariation.class).setProjection( Projections.rowCount() ).uniqueResult(), new Long(0) );
t.commit();
s.close();
+
+ assertUpdateCount( 0 );
+ assertDeleteCount( 3 );
}
public void testImmutableCollectionWithUpdate() {
- Contract c = new Contract("gavin", "phone");
+ clearCounts();
+
+ Contract c = new Contract( null, "gavin", "phone");
ContractVariation cv1 = new ContractVariation(1, c);
cv1.setText("expensive");
ContractVariation cv2 = new ContractVariation(2, c);
@@ -527,6 +663,9 @@ public class ImmutableTest extends FunctionalTestCase {
t.commit();
s.close();
+ assertInsertCount( 3 );
+ assertUpdateCount( 0 );
+
s = openSession();
t = s.beginTransaction();
c.getVariations().add( new ContractVariation(3, c) );
@@ -542,6 +681,8 @@ public class ImmutableTest extends FunctionalTestCase {
s.close();
}
+ assertUpdateCount( 0 );
+
s = openSession();
t = s.beginTransaction();
c = (Contract) s.createCriteria(Contract.class).uniqueResult();
@@ -557,10 +698,15 @@ public class ImmutableTest extends FunctionalTestCase {
assertEquals( s.createCriteria(ContractVariation.class).setProjection( Projections.rowCount() ).uniqueResult(), new Long(0) );
t.commit();
s.close();
+
+ assertUpdateCount( 0 );
+ assertDeleteCount( 3 );
}
- public void testImmutableParentEntityWithMerge() {
- Contract c = new Contract("gavin", "phone");
+ public void testUnmodifiedImmutableParentEntityWithMerge() {
+ clearCounts();
+
+ Contract c = new Contract( null, "gavin", "phone");
ContractVariation cv1 = new ContractVariation(1, c);
cv1.setText("expensive");
ContractVariation cv2 = new ContractVariation(2, c);
@@ -571,6 +717,65 @@ public class ImmutableTest extends FunctionalTestCase {
t.commit();
s.close();
+ assertInsertCount( 3 );
+ assertUpdateCount( 0 );
+ clearCounts();
+
+ s = openSession();
+ t = s.beginTransaction();
+ 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( cv1 ) );
+ assertTrue( s.isReadOnly( cv2 ) );
+ t.commit();
+ s.close();
+
+ assertUpdateCount( 0 );
+
+ s = openSession();
+ t = s.beginTransaction();
+ c = (Contract) s.createCriteria(Contract.class).uniqueResult();
+ assertEquals( c.getCustomerName(), "gavin" );
+ assertEquals( c.getVariations().size(), 2 );
+ it = c.getVariations().iterator();
+ cv1 = (ContractVariation) it.next();
+ assertEquals( cv1.getText(), "expensive" );
+ cv2 = (ContractVariation) it.next();
+ assertEquals( cv2.getText(), "more expensive" );
+ 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();
+
+ assertUpdateCount( 0 );
+ assertDeleteCount( 3 );
+ }
+
+ public void testImmutableParentEntityWithMerge() {
+ clearCounts();
+
+ Contract c = new Contract( null, "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();
+
+ assertInsertCount( 3 );
+ assertUpdateCount( 0 );
+ clearCounts();
+
s = openSession();
t = s.beginTransaction();
c.setCustomerName("foo bar");
@@ -587,6 +792,8 @@ public class ImmutableTest extends FunctionalTestCase {
t.commit();
s.close();
+ assertUpdateCount( 0 );
+
s = openSession();
t = s.beginTransaction();
c = (Contract) s.createCriteria(Contract.class).uniqueResult();
@@ -602,10 +809,16 @@ public class ImmutableTest extends FunctionalTestCase {
assertEquals( s.createCriteria(ContractVariation.class).setProjection( Projections.rowCount() ).uniqueResult(), new Long(0) );
t.commit();
s.close();
+
+ assertUpdateCount( 0 );
+ assertDeleteCount( 3 );
+
}
public void testImmutableChildEntityWithMerge() {
- Contract c = new Contract("gavin", "phone");
+ clearCounts();
+
+ Contract c = new Contract( null, "gavin", "phone");
ContractVariation cv1 = new ContractVariation(1, c);
cv1.setText("expensive");
ContractVariation cv2 = new ContractVariation(2, c);
@@ -616,6 +829,10 @@ public class ImmutableTest extends FunctionalTestCase {
t.commit();
s.close();
+ assertInsertCount( 3 );
+ assertUpdateCount( 0 );
+ clearCounts();
+
s = openSession();
t = s.beginTransaction();
cv1 = (ContractVariation) c.getVariations().iterator().next();
@@ -633,6 +850,8 @@ public class ImmutableTest extends FunctionalTestCase {
t.commit();
s.close();
+ assertUpdateCount( 0 );
+
s = openSession();
t = s.beginTransaction();
c = (Contract) s.createCriteria(Contract.class).uniqueResult();
@@ -648,10 +867,15 @@ public class ImmutableTest extends FunctionalTestCase {
assertEquals( s.createCriteria(ContractVariation.class).setProjection( Projections.rowCount() ).uniqueResult(), new Long(0) );
t.commit();
s.close();
+
+ assertUpdateCount( 0 );
+ assertDeleteCount( 3 );
}
public void testImmutableCollectionWithMerge() {
- Contract c = new Contract("gavin", "phone");
+ clearCounts();
+
+ Contract c = new Contract( null, "gavin", "phone");
ContractVariation cv1 = new ContractVariation(1, c);
cv1.setText("expensive");
ContractVariation cv2 = new ContractVariation(2, c);
@@ -662,6 +886,11 @@ public class ImmutableTest extends FunctionalTestCase {
t.commit();
s.close();
+ assertInsertCount( 3 );
+ assertUpdateCount( 0 );
+
+ clearCounts();
+
s = openSession();
t = s.beginTransaction();
c.getVariations().add( new ContractVariation(3, c) );
@@ -693,6 +922,28 @@ public class ImmutableTest extends FunctionalTestCase {
assertEquals( s.createCriteria(ContractVariation.class).setProjection( Projections.rowCount() ).uniqueResult(), new Long(0) );
t.commit();
s.close();
+
+ assertUpdateCount( 0 );
+ assertDeleteCount( 3 );
+ }
+
+ protected void clearCounts() {
+ getSessions().getStatistics().clear();
+ }
+
+ protected void assertInsertCount(int expected) {
+ int inserts = ( int ) getSessions().getStatistics().getEntityInsertCount();
+ assertEquals( "unexpected insert count", expected, inserts );
+ }
+
+ protected void assertUpdateCount(int expected) {
+ int updates = ( int ) getSessions().getStatistics().getEntityUpdateCount();
+ assertEquals( "unexpected update counts", expected, updates );
+ }
+
+ protected void assertDeleteCount(int expected) {
+ int deletes = ( int ) getSessions().getStatistics().getEntityDeleteCount();
+ assertEquals( "unexpected delete counts", expected, deletes );
}
}
diff --git a/testsuite/src/test/java/org/hibernate/test/immutable/Info.java b/testsuite/src/test/java/org/hibernate/test/immutable/Info.java
new file mode 100644
index 0000000000..911a2b94bc
--- /dev/null
+++ b/testsuite/src/test/java/org/hibernate/test/immutable/Info.java
@@ -0,0 +1,43 @@
+//$Id: Contract.java 7222 2005-06-19 17:22:01Z oneovthafew $
+package org.hibernate.test.immutable;
+
+import java.io.Serializable;
+
+public class Info implements Serializable {
+
+ private long id;
+ private String text;
+ private Contract contract;
+
+ public Info() {
+ super();
+ }
+
+ public Info(String text) {
+ this.text = text;
+ }
+
+ public String getText() {
+ return text;
+ }
+
+ public void setText(String text) {
+ this.text = text;
+ }
+
+ public long getId() {
+ return id;
+ }
+
+ public void setId(long id) {
+ this.id = id;
+ }
+
+ public Contract getContract() {
+ return contract;
+ }
+
+ public void setContract(Contract contract ) {
+ this.contract = contract;
+ }
+}
\ No newline at end of file
diff --git a/testsuite/src/test/java/org/hibernate/test/immutable/Party.java b/testsuite/src/test/java/org/hibernate/test/immutable/Party.java
new file mode 100644
index 0000000000..49d2740550
--- /dev/null
+++ b/testsuite/src/test/java/org/hibernate/test/immutable/Party.java
@@ -0,0 +1,47 @@
+//$Id: Contract.java 7222 2005-06-19 17:22:01Z oneovthafew $
+package org.hibernate.test.immutable;
+
+import java.io.Serializable;
+import java.util.ArrayList;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
+
+public class Party implements Serializable {
+
+ private long id;
+ private Contract contract;
+ private String name;
+
+ public Party() {
+ super();
+ }
+
+ public Party(String name) {
+ this.name = name;
+ }
+
+ public String getName() {
+ return name;
+ }
+
+ public void setName(String name) {
+ this.name = name;
+ }
+
+ public long getId() {
+ return id;
+ }
+
+ public void setId(long id) {
+ this.id = id;
+ }
+
+ public Contract getContract() {
+ return contract;
+ }
+
+ public void setContract(Contract contract) {
+ this.contract = contract;
+ }
+}
\ No newline at end of file
diff --git a/testsuite/src/test/java/org/hibernate/test/immutable/Plan.java b/testsuite/src/test/java/org/hibernate/test/immutable/Plan.java
new file mode 100644
index 0000000000..7810f6b9d1
--- /dev/null
+++ b/testsuite/src/test/java/org/hibernate/test/immutable/Plan.java
@@ -0,0 +1,80 @@
+//$Id: ContractVariation.java 7222 2005-06-19 17:22:01Z oneovthafew $
+package org.hibernate.test.immutable;
+
+import java.io.Serializable;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.Set;
+
+public class Plan implements Serializable {
+
+ private long id;
+ private String description;
+ private Set contracts;
+
+ public Plan() {
+ this( null );
+ }
+
+ public Plan(String description) {
+ this.description = description;
+ contracts = new HashSet();
+ }
+
+ public long getId() {
+ return id;
+ }
+
+ public void setId(long id) {
+ this.id = id;
+ }
+
+ public String getDescription() {
+ return description;
+ }
+
+ public void setDescription(String description) {
+ this.description = description;
+ }
+
+ public Set getContracts() {
+ return contracts;
+ }
+
+ public void setContracts(Set contracts) {
+ this.contracts = contracts;
+ }
+
+ public void addContract(Contract contract) {
+ if ( ! contracts.add( contract ) ) {
+ return;
+ }
+ if ( contract.getParent() != null ) {
+ addContract( contract.getParent() );
+ }
+ contract.getPlans().add( this );
+ for ( Iterator it=contract.getSubcontracts().iterator(); it.hasNext(); ) {
+ Contract sub = ( Contract ) it.next();
+ addContract( sub );
+ }
+ }
+
+ public void removeContract(Contract contract) {
+ if ( contract.getParent() != null ) {
+ contract.getParent().getSubcontracts().remove( contract );
+ contract.setParent( null );
+ }
+ removeSubcontracts( contract );
+ contract.getPlans().remove( this );
+ contracts.remove( contract );
+ }
+
+ public void removeSubcontracts(Contract contract) {
+ for ( Iterator it=contract.getSubcontracts().iterator(); it.hasNext(); ) {
+ Contract sub = ( Contract ) it.next();
+ removeSubcontracts( sub );
+ sub.getPlans().remove( this );
+ contracts.remove( sub );
+ }
+ }
+}
\ No newline at end of file
diff --git a/testsuite/src/test/java/org/hibernate/test/readonly/AbstractReadOnlyTest.java b/testsuite/src/test/java/org/hibernate/test/readonly/AbstractReadOnlyTest.java
new file mode 100644
index 0000000000..a48089ee92
--- /dev/null
+++ b/testsuite/src/test/java/org/hibernate/test/readonly/AbstractReadOnlyTest.java
@@ -0,0 +1,79 @@
+/*
+ * Hibernate, Relational Persistence for Idiomatic Java
+ *
+ * Copyright (c) 2010, Red Hat Middleware LLC or third-party contributors as
+ * indicated by the @author tags or express copyright attribution
+ * statements applied by the authors. All third-party contributions are
+ * distributed under license by Red Hat Middleware LLC.
+ *
+ * This copyrighted material is made available to anyone wishing to use, modify,
+ * copy, or redistribute it subject to the terms and conditions of the GNU
+ * Lesser General Public License, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
+ * for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this distribution; if not, write to:
+ * Free Software Foundation, Inc.
+ * 51 Franklin Street, Fifth Floor
+ * Boston, MA 02110-1301 USA
+ *
+ */
+package org.hibernate.test.readonly;
+
+import org.hibernate.CacheMode;
+import org.hibernate.cfg.Configuration;
+import org.hibernate.cfg.Environment;
+import org.hibernate.junit.functional.FunctionalTestCase;
+
+/**
+ *
+ * @author Gail Badner
+ */
+public abstract class AbstractReadOnlyTest extends FunctionalTestCase {
+
+ public AbstractReadOnlyTest(String str) {
+ super(str);
+ }
+
+ public void configure(Configuration cfg) {
+ cfg.setProperty( Environment.GENERATE_STATISTICS, "true");
+ cfg.setProperty( Environment.STATEMENT_BATCH_SIZE, "0" );
+ }
+
+ public org.hibernate.classic.Session openSession() {
+ org.hibernate.classic.Session s = super.openSession();
+ s.setCacheMode( getSessionCacheMode() );
+ return s;
+ }
+
+ protected CacheMode getSessionCacheMode() {
+ return CacheMode.IGNORE;
+ }
+
+ public String getCacheConcurrencyStrategy() {
+ return null;
+ }
+
+ protected void clearCounts() {
+ getSessions().getStatistics().clear();
+ }
+
+ protected void assertInsertCount(int expected) {
+ int inserts = ( int ) getSessions().getStatistics().getEntityInsertCount();
+ assertEquals( "unexpected insert count", expected, inserts );
+ }
+
+ protected void assertUpdateCount(int expected) {
+ int updates = ( int ) getSessions().getStatistics().getEntityUpdateCount();
+ assertEquals( "unexpected update counts", expected, updates );
+ }
+
+ protected void assertDeleteCount(int expected) {
+ int deletes = ( int ) getSessions().getStatistics().getEntityDeleteCount();
+ assertEquals( "unexpected delete counts", expected, deletes );
+ }
+}
\ No newline at end of file
diff --git a/testsuite/src/test/java/org/hibernate/test/readonly/criteria/Course.java b/testsuite/src/test/java/org/hibernate/test/readonly/Course.java
similarity index 90%
rename from testsuite/src/test/java/org/hibernate/test/readonly/criteria/Course.java
rename to testsuite/src/test/java/org/hibernate/test/readonly/Course.java
index 3a83671346..b296747847 100755
--- a/testsuite/src/test/java/org/hibernate/test/readonly/criteria/Course.java
+++ b/testsuite/src/test/java/org/hibernate/test/readonly/Course.java
@@ -1,5 +1,5 @@
//$Id: Course.java 5686 2005-02-12 07:27:32Z steveebersole $
-package org.hibernate.test.readonly.criteria;
+package org.hibernate.test.readonly;
/**
* @author Gavin King
diff --git a/testsuite/src/test/java/org/hibernate/test/readonly/DataPoint.hbm.xml b/testsuite/src/test/java/org/hibernate/test/readonly/DataPoint.hbm.xml
index 359824df98..9c0d4f7330 100755
--- a/testsuite/src/test/java/org/hibernate/test/readonly/DataPoint.hbm.xml
+++ b/testsuite/src/test/java/org/hibernate/test/readonly/DataPoint.hbm.xml
@@ -13,10 +13,10 @@
-
+
-
+
diff --git a/testsuite/src/test/java/org/hibernate/test/readonly/criteria/Enrolment.hbm.xml b/testsuite/src/test/java/org/hibernate/test/readonly/Enrolment.hbm.xml
similarity index 94%
rename from testsuite/src/test/java/org/hibernate/test/readonly/criteria/Enrolment.hbm.xml
rename to testsuite/src/test/java/org/hibernate/test/readonly/Enrolment.hbm.xml
index d2115b3f2a..83c7db5294 100755
--- a/testsuite/src/test/java/org/hibernate/test/readonly/criteria/Enrolment.hbm.xml
+++ b/testsuite/src/test/java/org/hibernate/test/readonly/Enrolment.hbm.xml
@@ -3,7 +3,7 @@
"-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
-
+
diff --git a/testsuite/src/test/java/org/hibernate/test/readonly/criteria/Enrolment.java b/testsuite/src/test/java/org/hibernate/test/readonly/Enrolment.java
similarity index 96%
rename from testsuite/src/test/java/org/hibernate/test/readonly/criteria/Enrolment.java
rename to testsuite/src/test/java/org/hibernate/test/readonly/Enrolment.java
index d48df67d3d..75469401fd 100755
--- a/testsuite/src/test/java/org/hibernate/test/readonly/criteria/Enrolment.java
+++ b/testsuite/src/test/java/org/hibernate/test/readonly/Enrolment.java
@@ -1,5 +1,5 @@
//$Id: Enrolment.java 6970 2005-05-31 20:24:41Z oneovthafew $
-package org.hibernate.test.readonly.criteria;
+package org.hibernate.test.readonly;
import java.io.Serializable;
diff --git a/testsuite/src/test/java/org/hibernate/test/readonly/criteria/ReadOnlyCriteriaQueryTest.java b/testsuite/src/test/java/org/hibernate/test/readonly/ReadOnlyCriteriaQueryTest.java
similarity index 99%
rename from testsuite/src/test/java/org/hibernate/test/readonly/criteria/ReadOnlyCriteriaQueryTest.java
rename to testsuite/src/test/java/org/hibernate/test/readonly/ReadOnlyCriteriaQueryTest.java
index 1a0ab8a966..8d0451993e 100755
--- a/testsuite/src/test/java/org/hibernate/test/readonly/criteria/ReadOnlyCriteriaQueryTest.java
+++ b/testsuite/src/test/java/org/hibernate/test/readonly/ReadOnlyCriteriaQueryTest.java
@@ -1,5 +1,5 @@
//$Id: CriteriaQueryTest.java 10976 2006-12-12 23:22:26Z steve.ebersole@jboss.com $
-package org.hibernate.test.readonly.criteria;
+package org.hibernate.test.readonly;
import java.util.Iterator;
import java.util.List;
@@ -7,6 +7,7 @@ import java.util.Map;
import junit.framework.Test;
+import org.hibernate.CacheMode;
import org.hibernate.Criteria;
import org.hibernate.FetchMode;
import org.hibernate.Hibernate;
@@ -30,6 +31,7 @@ import org.hibernate.proxy.HibernateProxy;
import org.hibernate.proxy.LazyInitializer;
import org.hibernate.test.hql.Animal;
import org.hibernate.test.hql.Reptile;
+import org.hibernate.test.readonly.AbstractReadOnlyTest;
import org.hibernate.transform.Transformers;
import org.hibernate.type.Type;
import org.hibernate.util.SerializationHelper;
@@ -37,14 +39,14 @@ import org.hibernate.util.SerializationHelper;
/**
* @author Gail Badner (adapted from org.hibernate.test.criteria.CriteriaQueryTest by Gavin King)
*/
-public class ReadOnlyCriteriaQueryTest extends FunctionalTestCase {
+public class ReadOnlyCriteriaQueryTest extends AbstractReadOnlyTest {
public ReadOnlyCriteriaQueryTest(String str) {
super(str);
}
public String[] getMappings() {
- return new String[] { "readonly/criteria/Enrolment.hbm.xml" };
+ return new String[] { "readonly/Enrolment.hbm.xml" };
}
public void configure(Configuration cfg) {
@@ -54,7 +56,7 @@ public class ReadOnlyCriteriaQueryTest extends FunctionalTestCase {
cfg.setProperty( Environment.USE_SECOND_LEVEL_CACHE, "true" );
cfg.setProperty( Environment.GENERATE_STATISTICS, "true" );
}
-
+
public static Test suite() {
return new FunctionalTestClassTestSuite( ReadOnlyCriteriaQueryTest.class );
}
@@ -92,6 +94,10 @@ public class ReadOnlyCriteriaQueryTest extends FunctionalTestCase {
t.commit();
s.close();
+ assertInsertCount( 4 );
+ assertUpdateCount( 0 );
+ clearCounts();
+
s = openSession();
t = s.beginTransaction();
Criteria criteria = s.createCriteria( Student.class );
@@ -125,6 +131,9 @@ public class ReadOnlyCriteriaQueryTest extends FunctionalTestCase {
s.delete(enrolment);
t.commit();
s.close();
+
+ assertUpdateCount( 1 );
+ assertDeleteCount( 4 );
}
public void testModifiableSessionReadOnlyCriteria() {
diff --git a/testsuite/src/test/java/org/hibernate/test/readonly/ReadOnlyProxyTest.java b/testsuite/src/test/java/org/hibernate/test/readonly/ReadOnlyProxyTest.java
index 328e897baf..7e6f549e5f 100644
--- a/testsuite/src/test/java/org/hibernate/test/readonly/ReadOnlyProxyTest.java
+++ b/testsuite/src/test/java/org/hibernate/test/readonly/ReadOnlyProxyTest.java
@@ -52,7 +52,7 @@ import org.hibernate.junit.functional.FunctionalTestClassTestSuite;
*
* @author Gail Badner
*/
-public class ReadOnlyProxyTest extends FunctionalTestCase {
+public class ReadOnlyProxyTest extends AbstractReadOnlyTest {
public ReadOnlyProxyTest(String str) {
super(str);
@@ -62,14 +62,6 @@ public class ReadOnlyProxyTest extends FunctionalTestCase {
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( ReadOnlyProxyTest.class );
}
diff --git a/testsuite/src/test/java/org/hibernate/test/readonly/ReadOnlySessionLazyNonLazyTest.java b/testsuite/src/test/java/org/hibernate/test/readonly/ReadOnlySessionLazyNonLazyTest.java
index 1bddb921e5..8b9a90fa66 100644
--- a/testsuite/src/test/java/org/hibernate/test/readonly/ReadOnlySessionLazyNonLazyTest.java
+++ b/testsuite/src/test/java/org/hibernate/test/readonly/ReadOnlySessionLazyNonLazyTest.java
@@ -66,7 +66,7 @@ import org.hibernate.junit.functional.FunctionalTestClassTestSuite;
*
* @author Gail Badner
*/
-public class ReadOnlySessionLazyNonLazyTest extends FunctionalTestCase {
+public class ReadOnlySessionLazyNonLazyTest extends AbstractReadOnlyTest {
public ReadOnlySessionLazyNonLazyTest(String str) {
super(str);
@@ -76,14 +76,6 @@ public class ReadOnlySessionLazyNonLazyTest extends FunctionalTestCase {
return new String[] { "readonly/DataPoint.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( ReadOnlySessionLazyNonLazyTest.class );
}
@@ -106,7 +98,6 @@ public class ReadOnlySessionLazyNonLazyTest extends FunctionalTestCase {
Session s = openSession();
assertFalse( s.isDefaultReadOnly() );
- s.setCacheMode(CacheMode.IGNORE);
Transaction t = s.beginTransaction();
s.save( cOrig );
checkContainer( cOrig, expectedInitializedObjects, expectedReadOnlyObjects, s );
@@ -195,7 +186,6 @@ public class ReadOnlySessionLazyNonLazyTest extends FunctionalTestCase {
Set expectedReadOnlyObjects = new HashSet();
Session s = openSession();
assertFalse( s.isDefaultReadOnly() );
- s.setCacheMode(CacheMode.IGNORE);
Transaction t = s.beginTransaction();
s.save( cOrig );
checkContainer( cOrig, expectedInitializedObjects, expectedReadOnlyObjects, s );
@@ -278,7 +268,6 @@ public class ReadOnlySessionLazyNonLazyTest extends FunctionalTestCase {
DataPoint lazyDataPointOrig = ( DataPoint ) cOrig.getLazyDataPoints().iterator().next();
Session s = openSession();
assertFalse( s.isDefaultReadOnly() );
- s.setCacheMode(CacheMode.IGNORE);
Transaction t = s.beginTransaction();
s.save( cOrig );
checkContainer( cOrig, expectedInitializedObjects, expectedReadOnlyObjects, s );
@@ -362,7 +351,6 @@ public class ReadOnlySessionLazyNonLazyTest extends FunctionalTestCase {
DataPoint lazyDataPointOrig = ( DataPoint ) cOrig.getLazyDataPoints().iterator().next();
Session s = openSession();
assertFalse( s.isDefaultReadOnly() );
- s.setCacheMode(CacheMode.IGNORE);
Transaction t = s.beginTransaction();
s.save( cOrig );
checkContainer( cOrig, expectedInitializedObjects, expectedReadOnlyObjects, s );
@@ -449,7 +437,6 @@ public class ReadOnlySessionLazyNonLazyTest extends FunctionalTestCase {
DataPoint lazyDataPointOrig = ( DataPoint ) cOrig.getLazyDataPoints().iterator().next();
Session s = openSession();
assertFalse( s.isDefaultReadOnly() );
- s.setCacheMode(CacheMode.IGNORE);
Transaction t = s.beginTransaction();
s.save( cOrig );
checkContainer( cOrig, expectedInitializedObjects, expectedReadOnlyObjects, s );
@@ -533,7 +520,6 @@ public class ReadOnlySessionLazyNonLazyTest extends FunctionalTestCase {
DataPoint lazyDataPointOrig = ( DataPoint ) cOrig.getLazyDataPoints().iterator().next();
Session s = openSession();
assertFalse( s.isDefaultReadOnly() );
- s.setCacheMode(CacheMode.IGNORE);
Transaction t = s.beginTransaction();
s.save( cOrig );
checkContainer( cOrig, expectedInitializedObjects, expectedReadOnlyObjects, s );
@@ -618,7 +604,6 @@ public class ReadOnlySessionLazyNonLazyTest extends FunctionalTestCase {
Session s = openSession();
assertFalse( s.isDefaultReadOnly() );
- s.setCacheMode(CacheMode.IGNORE);
Transaction t = s.beginTransaction();
s.save( cOrig );
checkContainer( cOrig, expectedInitializedObjects, expectedReadOnlyObjects, s );
@@ -697,7 +682,6 @@ public class ReadOnlySessionLazyNonLazyTest extends FunctionalTestCase {
Session s = openSession();
assertFalse( s.isDefaultReadOnly() );
- s.setCacheMode(CacheMode.IGNORE);
Transaction t = s.beginTransaction();
s.save( cOrig );
checkContainer( cOrig, expectedInitializedObjects, expectedReadOnlyObjects, s );
@@ -767,7 +751,6 @@ public class ReadOnlySessionLazyNonLazyTest extends FunctionalTestCase {
Session s = openSession();
assertFalse( s.isDefaultReadOnly() );
- s.setCacheMode(CacheMode.IGNORE);
Transaction t = s.beginTransaction();
s.save( cOrig );
checkContainer( cOrig, expectedInitializedObjects, expectedReadOnlyObjects, s );
@@ -847,7 +830,6 @@ public class ReadOnlySessionLazyNonLazyTest extends FunctionalTestCase {
Session s = openSession();
assertFalse( s.isDefaultReadOnly() );
- s.setCacheMode(CacheMode.IGNORE);
Transaction t = s.beginTransaction();
s.save( cOrig );
checkContainer( cOrig, expectedInitializedObjects, expectedReadOnlyObjects, s );
@@ -916,7 +898,6 @@ public class ReadOnlySessionLazyNonLazyTest extends FunctionalTestCase {
Session s = openSession();
assertFalse( s.isDefaultReadOnly() );
- s.setCacheMode(CacheMode.IGNORE);
Transaction t = s.beginTransaction();
s.save( cOrig );
checkContainer( cOrig, expectedInitializedObjects, expectedReadOnlyObjects, s );
@@ -961,7 +942,6 @@ public class ReadOnlySessionLazyNonLazyTest extends FunctionalTestCase {
Session s = openSession();
assertFalse( s.isDefaultReadOnly() );
- s.setCacheMode(CacheMode.IGNORE);
Transaction t = s.beginTransaction();
s.save( cOrig );
checkContainer( cOrig, expectedInitializedObjects, expectedReadOnlyObjects, s );
@@ -1045,7 +1025,6 @@ public class ReadOnlySessionLazyNonLazyTest extends FunctionalTestCase {
Session s = openSession();
assertFalse( s.isDefaultReadOnly() );
- s.setCacheMode(CacheMode.IGNORE);
Transaction t = s.beginTransaction();
s.save( cOrig );
checkContainer( cOrig, expectedInitializedObjects, expectedReadOnlyObjects, s );
@@ -1118,7 +1097,6 @@ public class ReadOnlySessionLazyNonLazyTest extends FunctionalTestCase {
Session s = openSession();
assertFalse( s.isDefaultReadOnly() );
- s.setCacheMode(CacheMode.IGNORE);
Transaction t = s.beginTransaction();
s.save( cOrig );
checkContainer( cOrig, expectedInitializedObjects, expectedReadOnlyObjects, s );
@@ -1199,7 +1177,6 @@ public class ReadOnlySessionLazyNonLazyTest extends FunctionalTestCase {
Session s = openSession();
assertFalse( s.isDefaultReadOnly() );
- s.setCacheMode(CacheMode.IGNORE);
Transaction t = s.beginTransaction();
s.save( cOrig );
checkContainer( cOrig, expectedInitializedObjects, expectedReadOnlyObjects, s );
@@ -1257,14 +1234,12 @@ public class ReadOnlySessionLazyNonLazyTest extends FunctionalTestCase {
Container cOrig = createContainer();
Session s = openSession();
- s.setCacheMode(CacheMode.IGNORE);
Transaction t = s.beginTransaction();
s.save( cOrig );
t.commit();
s.close();
s = openSession();
- s.setCacheMode(CacheMode.IGNORE);
t = s.beginTransaction();
List list = s.createQuery( "from Container c left outer join c.nonLazyInfo where c.id = :id" )
.setLong( "id", cOrig.getId() )
@@ -1301,14 +1276,12 @@ public class ReadOnlySessionLazyNonLazyTest extends FunctionalTestCase {
Container cOrig = createContainer();
Session s = openSession();
- s.setCacheMode(CacheMode.IGNORE);
Transaction t = s.beginTransaction();
s.save( cOrig );
t.commit();
s.close();
s = openSession();
- s.setCacheMode(CacheMode.IGNORE);
t = s.beginTransaction();
List list = s.createQuery( "from Container c left join fetch c.nonLazyInfo where c.id = :id" )
.setLong( "id", cOrig.getId() )
@@ -1348,14 +1321,12 @@ public class ReadOnlySessionLazyNonLazyTest extends FunctionalTestCase {
Container cOrig = createContainer();
Session s = openSession();
- s.setCacheMode(CacheMode.IGNORE);
Transaction t = s.beginTransaction();
s.save( cOrig );
t.commit();
s.close();
s = openSession();
- s.setCacheMode(CacheMode.IGNORE);
t = s.beginTransaction();
Container c = ( Container ) s.get( Container.class, cOrig.getId() );
assertNotNull( c );
diff --git a/testsuite/src/test/java/org/hibernate/test/readonly/ReadOnlySessionTest.java b/testsuite/src/test/java/org/hibernate/test/readonly/ReadOnlySessionTest.java
index 79648bade9..7c44bc77a3 100644
--- a/testsuite/src/test/java/org/hibernate/test/readonly/ReadOnlySessionTest.java
+++ b/testsuite/src/test/java/org/hibernate/test/readonly/ReadOnlySessionTest.java
@@ -48,7 +48,7 @@ import org.hibernate.proxy.HibernateProxy;
*
* @author Gail Badner
*/
-public class ReadOnlySessionTest extends FunctionalTestCase {
+public class ReadOnlySessionTest extends AbstractReadOnlyTest {
public ReadOnlySessionTest(String str) {
super(str);
@@ -58,14 +58,6 @@ public class ReadOnlySessionTest extends FunctionalTestCase {
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 );
}
diff --git a/testsuite/src/test/java/org/hibernate/test/readonly/ReadOnlyTest.java b/testsuite/src/test/java/org/hibernate/test/readonly/ReadOnlyTest.java
index f83f13f2d8..4cb0e05560 100755
--- a/testsuite/src/test/java/org/hibernate/test/readonly/ReadOnlyTest.java
+++ b/testsuite/src/test/java/org/hibernate/test/readonly/ReadOnlyTest.java
@@ -47,7 +47,7 @@ import org.hibernate.junit.functional.FunctionalTestClassTestSuite;
* @author Gavin King
* @author Gail Badner
*/
-public class ReadOnlyTest extends FunctionalTestCase {
+public class ReadOnlyTest extends AbstractReadOnlyTest {
public ReadOnlyTest(String str) {
super(str);
@@ -57,21 +57,14 @@ public class ReadOnlyTest extends FunctionalTestCase {
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( ReadOnlyTest.class );
}
public void testReadOnlyOnProxies() {
+ clearCounts();
+
Session s = openSession();
- s.setCacheMode( CacheMode.IGNORE );
s.beginTransaction();
DataPoint dp = new DataPoint();
dp.setX( new BigDecimal( 0.1d ).setScale(19, BigDecimal.ROUND_DOWN) );
@@ -82,8 +75,11 @@ public class ReadOnlyTest extends FunctionalTestCase {
s.getTransaction().commit();
s.close();
+ assertInsertCount( 1 );
+ assertUpdateCount( 0 );
+ clearCounts();
+
s = openSession();
- s.setCacheMode(CacheMode.IGNORE);
s.beginTransaction();
dp = ( DataPoint ) s.load( DataPoint.class, new Long( dpId ) );
assertFalse( "was initialized", Hibernate.isInitialized( dp ) );
@@ -96,20 +92,27 @@ public class ReadOnlyTest extends FunctionalTestCase {
s.getTransaction().commit();
s.close();
+ assertUpdateCount( 0 );
+
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();
+ assertEquals( 1, s.createQuery("delete from DataPoint").executeUpdate() );
s.getTransaction().commit();
s.close();
+
+ assertUpdateCount( 0 );
+ //deletes from Query.executeUpdate() are not tracked
+ //assertDeleteCount( 1 );
}
public void testReadOnlyMode() {
-
+
+ clearCounts();
+
Session s = openSession();
- s.setCacheMode(CacheMode.IGNORE);
- Transaction t = s.beginTransaction();
+ 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) );
@@ -118,9 +121,12 @@ public class ReadOnlyTest extends FunctionalTestCase {
}
t.commit();
s.close();
-
+
+ assertInsertCount( 100 );
+ assertUpdateCount( 0 );
+ clearCounts();
+
s = openSession();
- s.setCacheMode(CacheMode.IGNORE);
t = s.beginTransaction();
int i = 0;
ScrollableResults sr = s.createQuery("from DataPoint dp order by dp.x asc")
@@ -134,20 +140,27 @@ public class ReadOnlyTest extends FunctionalTestCase {
dp.setDescription("done!");
}
t.commit();
+
+ assertUpdateCount( 1 );
+ clearCounts();
+
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();
+ assertEquals( 100, s.createQuery("delete from DataPoint").executeUpdate() );
t.commit();
s.close();
-
+
+ assertUpdateCount( 0 );
+ //deletes from Query.executeUpdate() are not tracked
+ //assertDeleteCount( 100 );
}
public void testReadOnlyModeAutoFlushOnQuery() {
+ clearCounts();
Session s = openSession();
- s.setCacheMode(CacheMode.IGNORE);
Transaction t = s.beginTransaction();
DataPoint dpFirst = null;
for ( int i=0; i<100; i++ ) {
@@ -156,9 +169,18 @@ public class ReadOnlyTest extends FunctionalTestCase {
dp.setY( new BigDecimal( Math.cos( dp.getX().doubleValue() ) ).setScale(19, BigDecimal.ROUND_DOWN) );
s.save(dp);
}
+
+ assertInsertCount( 0 );
+ assertUpdateCount( 0 );
+
ScrollableResults sr = s.createQuery("from DataPoint dp order by dp.x asc")
.setReadOnly(true)
.scroll(ScrollMode.FORWARD_ONLY);
+
+ assertInsertCount( 100 );
+ assertUpdateCount( 0 );
+ clearCounts();
+
while ( sr.next() ) {
DataPoint dp = (DataPoint) sr.get(0);
assertFalse( s.isReadOnly( dp ) );
@@ -167,23 +189,30 @@ public class ReadOnlyTest extends FunctionalTestCase {
t.commit();
s.close();
+ assertUpdateCount( 0 );
+ assertDeleteCount( 100 );
}
- public void testReadOnlyRefresh() {
+ public void testSaveReadOnlyModifyInSaveTransaction() {
+ clearCounts();
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);
+ s.setReadOnly( dp, true );
+ dp.setDescription( "different" );
t.commit();
s.close();
+ assertInsertCount( 1 );
+ assertUpdateCount( 0 );
+ clearCounts();
+
s = openSession();
- s.setCacheMode(CacheMode.IGNORE);
t = s.beginTransaction();
dp = ( DataPoint ) s.get( DataPoint.class, dp.getId() );
s.setReadOnly( dp, true );
@@ -196,6 +225,9 @@ public class ReadOnlyTest extends FunctionalTestCase {
assertEquals( "changed", dp.getDescription() );
t.commit();
+ assertInsertCount( 0 );
+ assertUpdateCount( 0 );
+
s.clear();
t = s.beginTransaction();
dp = ( DataPoint ) s.get( DataPoint.class, dp.getId() );
@@ -204,12 +236,15 @@ public class ReadOnlyTest extends FunctionalTestCase {
t.commit();
s.close();
+ assertUpdateCount( 0 );
+ assertDeleteCount( 1 );
+ clearCounts();
}
- public void testReadOnlyRefreshDetached() {
+ public void testReadOnlyRefresh() {
+ clearCounts();
Session s = openSession();
- s.setCacheMode(CacheMode.IGNORE);
Transaction t = s.beginTransaction();
DataPoint dp = new DataPoint();
dp.setDescription( "original" );
@@ -219,8 +254,57 @@ public class ReadOnlyTest extends FunctionalTestCase {
t.commit();
s.close();
+ assertInsertCount( 1 );
+ assertUpdateCount( 0 );
+ clearCounts();
+
+ s = openSession();
+ t = s.beginTransaction();
+ dp = ( DataPoint ) s.get( DataPoint.class, dp.getId() );
+ s.setReadOnly( dp, true );
+ assertEquals( "original", dp.getDescription() );
+ dp.setDescription( "changed" );
+ assertEquals( "changed", dp.getDescription() );
+ s.refresh( dp );
+ assertEquals( "original", dp.getDescription() );
+ dp.setDescription( "changed" );
+ assertEquals( "changed", dp.getDescription() );
+ t.commit();
+
+ assertInsertCount( 0 );
+ assertUpdateCount( 0 );
+
+ s.clear();
+ t = s.beginTransaction();
+ dp = ( DataPoint ) s.get( DataPoint.class, dp.getId() );
+ assertEquals( "original", dp.getDescription() );
+ s.delete( dp );
+ t.commit();
+ s.close();
+
+ assertUpdateCount( 0 );
+ assertDeleteCount( 1 );
+ clearCounts();
+ }
+
+ public void testReadOnlyRefreshDetached() {
+ clearCounts();
+
+ Session s = openSession();
+ 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();
+
+ assertInsertCount( 1 );
+ assertUpdateCount( 0 );
+ clearCounts();
+
s = openSession();
- s.setCacheMode(CacheMode.IGNORE);
t = s.beginTransaction();
dp.setDescription( "changed" );
assertEquals( "changed", dp.getDescription() );
@@ -236,6 +320,9 @@ public class ReadOnlyTest extends FunctionalTestCase {
assertFalse( s.isReadOnly( dp ) );
t.commit();
+ assertInsertCount( 0 );
+ assertUpdateCount( 0 );
+
s.clear();
t = s.beginTransaction();
dp = ( DataPoint ) s.get( DataPoint.class, dp.getId() );
@@ -243,12 +330,16 @@ public class ReadOnlyTest extends FunctionalTestCase {
s.delete( dp );
t.commit();
s.close();
+
+ assertUpdateCount( 0 );
+ assertDeleteCount( 1 );
}
public void testReadOnlyDelete() {
+ clearCounts();
+
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) );
@@ -257,8 +348,11 @@ public class ReadOnlyTest extends FunctionalTestCase {
t.commit();
s.close();
+ assertInsertCount( 1 );
+ assertUpdateCount( 0 );
+ clearCounts();
+
s = openSession();
- s.setCacheMode(CacheMode.IGNORE);
t = s.beginTransaction();
dp = ( DataPoint ) s.get( DataPoint.class, dp.getId() );
s.setReadOnly( dp, true );
@@ -266,6 +360,9 @@ public class ReadOnlyTest extends FunctionalTestCase {
t.commit();
s.close();
+ assertUpdateCount( 0 );
+ assertDeleteCount( 1 );
+
s = openSession();
t = s.beginTransaction();
List list = s.createQuery("from DataPoint where description='done!'").list();
@@ -276,9 +373,9 @@ public class ReadOnlyTest extends FunctionalTestCase {
}
public void testReadOnlyGetModifyAndDelete() {
+ clearCounts();
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) );
@@ -287,8 +384,11 @@ public class ReadOnlyTest extends FunctionalTestCase {
t.commit();
s.close();
+ assertInsertCount( 1 );
+ assertUpdateCount( 0 );
+ clearCounts();
+
s = openSession();
- s.setCacheMode(CacheMode.IGNORE);
t = s.beginTransaction();
dp = ( DataPoint ) s.get( DataPoint.class, dp.getId() );
s.setReadOnly( dp, true );
@@ -297,6 +397,10 @@ public class ReadOnlyTest extends FunctionalTestCase {
t.commit();
s.close();
+ assertUpdateCount( 0 );
+ assertDeleteCount( 1 );
+ clearCounts();
+
s = openSession();
t = s.beginTransaction();
List list = s.createQuery("from DataPoint where description='done!'").list();
@@ -307,9 +411,9 @@ public class ReadOnlyTest extends FunctionalTestCase {
}
public void testReadOnlyModeWithExistingModifiableEntity() {
+ clearCounts();
Session s = openSession();
- s.setCacheMode(CacheMode.IGNORE);
Transaction t = s.beginTransaction();
DataPoint dp = null;
for ( int i=0; i<100; i++ ) {
@@ -321,8 +425,11 @@ public class ReadOnlyTest extends FunctionalTestCase {
t.commit();
s.close();
+ assertInsertCount( 100 );
+ assertUpdateCount( 0 );
+ clearCounts();
+
s = openSession();
- s.setCacheMode(CacheMode.IGNORE);
t = s.beginTransaction();
DataPoint dpLast = ( DataPoint ) s.get( DataPoint.class, dp.getId() );
assertFalse( s.isReadOnly( dpLast ) );
@@ -348,18 +455,25 @@ public class ReadOnlyTest extends FunctionalTestCase {
}
t.commit();
s.clear();
+
+ assertInsertCount( 0 );
+ assertUpdateCount( nExpectedChanges );
+ clearCounts();
+
t = s.beginTransaction();
List list = s.createQuery("from DataPoint where description='done!'").list();
assertEquals( list.size(), nExpectedChanges );
- s.createQuery("delete from DataPoint").executeUpdate();
+ assertEquals( 100, s.createQuery("delete from DataPoint").executeUpdate() );
t.commit();
s.close();
+
+ assertUpdateCount( 0 );
}
public void testModifiableModeWithExistingReadOnlyEntity() {
+ clearCounts();
Session s = openSession();
- s.setCacheMode(CacheMode.IGNORE);
Transaction t = s.beginTransaction();
DataPoint dp = null;
for ( int i=0; i<100; i++ ) {
@@ -371,14 +485,21 @@ public class ReadOnlyTest extends FunctionalTestCase {
t.commit();
s.close();
+ assertInsertCount( 100 );
+ assertUpdateCount( 0 );
+ clearCounts();
+
s = openSession();
- s.setCacheMode(CacheMode.IGNORE);
t = s.beginTransaction();
DataPoint dpLast = ( DataPoint ) s.get( DataPoint.class, dp.getId() );
assertFalse( s.isReadOnly( dpLast ) );
s.setReadOnly( dpLast, true );
assertTrue( s.isReadOnly( dpLast ) );
+ dpLast.setDescription( "oy" );
int i = 0;
+
+ assertUpdateCount( 0 );
+
ScrollableResults sr = s.createQuery("from DataPoint dp order by dp.x asc")
.setReadOnly(false)
.scroll(ScrollMode.FORWARD_ONLY);
@@ -400,30 +521,40 @@ public class ReadOnlyTest extends FunctionalTestCase {
}
t.commit();
s.clear();
+
+ assertUpdateCount( nExpectedChanges );
+ clearCounts();
+
t = s.beginTransaction();
List list = s.createQuery("from DataPoint where description='done!'").list();
assertEquals( list.size(), nExpectedChanges );
- s.createQuery("delete from DataPoint").executeUpdate();
+ assertEquals( 100, s.createQuery("delete from DataPoint").executeUpdate() );
t.commit();
s.close();
+
+ assertUpdateCount( 0 );
}
public void testReadOnlyOnTextType() {
final String origText = "some huge text string";
final String newText = "some even bigger text string";
+ clearCounts();
+
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();
+ assertInsertCount( 1 );
+ assertUpdateCount( 0 );
+ clearCounts();
+
s = openSession();
s.beginTransaction();
- s.setCacheMode( CacheMode.IGNORE );
holder = ( TextHolder ) s.get( TextHolder.class, id );
s.setReadOnly( holder, true );
holder.setTheText( newText );
@@ -431,6 +562,8 @@ public class ReadOnlyTest extends FunctionalTestCase {
s.getTransaction().commit();
s.close();
+ assertUpdateCount( 0 );
+
s = openSession();
s.beginTransaction();
holder = ( TextHolder ) s.get( TextHolder.class, id );
@@ -438,12 +571,15 @@ public class ReadOnlyTest extends FunctionalTestCase {
s.delete( holder );
s.getTransaction().commit();
s.close();
+
+ assertUpdateCount( 0 );
+ assertDeleteCount( 1 );
}
public void testMergeWithReadOnlyEntity() {
+ clearCounts();
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) );
@@ -452,10 +588,13 @@ public class ReadOnlyTest extends FunctionalTestCase {
t.commit();
s.close();
+ assertInsertCount( 1 );
+ assertUpdateCount( 0 );
+ clearCounts();
+
dp.setDescription( "description" );
s = openSession();
- s.setCacheMode(CacheMode.IGNORE);
t = s.beginTransaction();
DataPoint dpManaged = ( DataPoint ) s.get( DataPoint.class, new Long( dp.getId() ) );
s.setReadOnly( dpManaged, true );
@@ -464,6 +603,8 @@ public class ReadOnlyTest extends FunctionalTestCase {
t.commit();
s.close();
+ assertUpdateCount( 0 );
+
s = openSession();
t = s.beginTransaction();
dpManaged = ( DataPoint ) s.get( DataPoint.class, new Long( dp.getId() ) );
@@ -472,6 +613,9 @@ public class ReadOnlyTest extends FunctionalTestCase {
t.commit();
s.close();
+ assertUpdateCount( 0 );
+ assertDeleteCount( 1 );
+
}
}
diff --git a/testsuite/src/test/java/org/hibernate/test/readonly/ReadOnlyVersionedNodesTest.java b/testsuite/src/test/java/org/hibernate/test/readonly/ReadOnlyVersionedNodesTest.java
index 599c8db9c8..ffe1842360 100644
--- a/testsuite/src/test/java/org/hibernate/test/readonly/ReadOnlyVersionedNodesTest.java
+++ b/testsuite/src/test/java/org/hibernate/test/readonly/ReadOnlyVersionedNodesTest.java
@@ -36,7 +36,7 @@ import org.hibernate.cfg.Environment;
/**
* @author Gail Badner
*/
-public class ReadOnlyVersionedNodesTest extends FunctionalTestCase {
+public class ReadOnlyVersionedNodesTest extends AbstractReadOnlyTest {
public ReadOnlyVersionedNodesTest(String str) {
super( str );
@@ -46,15 +46,6 @@ public class ReadOnlyVersionedNodesTest extends FunctionalTestCase {
return new String[] { "readonly/VersionedNode.hbm.xml" };
}
- public String getCacheConcurrencyStrategy() {
- return null;
- }
-
- public void configure(Configuration cfg) {
- cfg.setProperty( Environment.GENERATE_STATISTICS, "true");
- cfg.setProperty( Environment.STATEMENT_BATCH_SIZE, "0" );
- }
-
public static Test suite() {
return new FunctionalTestClassTestSuite( ReadOnlyVersionedNodesTest.class );
}
@@ -116,15 +107,20 @@ public class ReadOnlyVersionedNodesTest extends FunctionalTestCase {
assertUpdateCount( 1 );
assertInsertCount( 0 );
+ clearCounts();
s = openSession();
s.beginTransaction();
node = ( VersionedNode ) s.get( VersionedNode.class, node.getId() );
assertEquals( "diff-node-name", node.getName() );
assertEquals( 1, node.getVersion() );
+ s.setReadOnly( node, true );
s.delete( node );
s.getTransaction().commit();
s.close();
+
+ assertUpdateCount( 0 );
+ assertDeleteCount( 1 );
}
public void testUpdateSetReadOnlyTwice() throws Exception {
@@ -155,9 +151,13 @@ public class ReadOnlyVersionedNodesTest extends FunctionalTestCase {
node = ( VersionedNode ) s.get( VersionedNode.class, node.getId() );
assertEquals( "node", node.getName() );
assertEquals( 0, node.getVersion() );
+ s.setReadOnly( node, true );
s.delete( node );
s.getTransaction().commit();
s.close();
+
+ assertUpdateCount( 0 );
+ assertDeleteCount( 1 );
}
public void testUpdateSetModifiable() throws Exception {
@@ -181,15 +181,20 @@ public class ReadOnlyVersionedNodesTest extends FunctionalTestCase {
assertUpdateCount( 1 );
assertInsertCount( 0 );
+ clearCounts();
s = openSession();
s.beginTransaction();
node = ( VersionedNode ) s.get( VersionedNode.class, node.getId() );
assertEquals( "node-name", node.getName() );
assertEquals( 1, node.getVersion() );
+ s.setReadOnly( node, true );
s.delete( node );
s.getTransaction().commit();
s.close();
+
+ assertUpdateCount( 0 );
+ assertDeleteCount( 1 );
}
public void testUpdateSetReadOnlySetModifiableFailureExpected() throws Exception {
@@ -317,6 +322,7 @@ public class ReadOnlyVersionedNodesTest extends FunctionalTestCase {
assertUpdateCount( 0 );
assertInsertCount( 1 );
+ clearCounts();
s = openSession();
s.beginTransaction();
@@ -328,10 +334,15 @@ public class ReadOnlyVersionedNodesTest extends FunctionalTestCase {
assertSame( parent, child.getParent() );
assertSame( child, parent.getChildren().iterator().next() );
assertEquals( 0, child.getVersion() );
+ s.setReadOnly( parent, true );
+ s.setReadOnly( child, true );
s.delete( parent );
s.delete( child );
s.getTransaction().commit();
s.close();
+
+ assertUpdateCount( 0 );
+ assertDeleteCount( 2 );
}
public void testMergeDetachedParentWithNewChildCommitWithReadOnlyParent() throws Exception {
@@ -357,6 +368,7 @@ public class ReadOnlyVersionedNodesTest extends FunctionalTestCase {
assertUpdateCount( 0 );
assertInsertCount( 1 );
+ clearCounts();
s = openSession();
s.beginTransaction();
@@ -368,10 +380,15 @@ public class ReadOnlyVersionedNodesTest extends FunctionalTestCase {
assertSame( parent, child.getParent() );
assertSame( child, parent.getChildren().iterator().next() );
assertEquals( 0, child.getVersion() );
+ s.setReadOnly( parent, true );
+ s.setReadOnly( child, true );
s.delete( parent );
s.delete( child );
s.getTransaction().commit();
s.close();
+
+ assertUpdateCount( 0 );
+ assertDeleteCount( 2 );
}
public void testGetParentMakeReadOnlyThenMergeDetachedParentWithNewChildC() throws Exception {
@@ -399,6 +416,7 @@ public class ReadOnlyVersionedNodesTest extends FunctionalTestCase {
assertUpdateCount( 0 );
assertInsertCount( 1 );
+ clearCounts();
s = openSession();
s.beginTransaction();
@@ -414,8 +432,73 @@ public class ReadOnlyVersionedNodesTest extends FunctionalTestCase {
s.delete( child );
s.getTransaction().commit();
s.close();
+
+ assertUpdateCount( 0 );
+ assertDeleteCount( 2 );
}
+ public void testMergeUnchangedDetachedParentChildren() throws Exception {
+ Session s = openSession();
+ s.beginTransaction();
+ VersionedNode parent = new VersionedNode( "parent", "parent" );
+ VersionedNode child = new VersionedNode( "child", "child");
+ parent.addChild( child );
+ s.persist( parent );
+ s.getTransaction().commit();
+ s.close();
+
+ clearCounts();
+
+ s = openSession();
+ s.beginTransaction();
+ parent = ( VersionedNode ) s.merge( parent );
+ s.getTransaction().commit();
+ s.close();
+
+ assertUpdateCount( 0 );
+ assertInsertCount( 0 );
+ clearCounts();
+
+ s = openSession();
+ s.beginTransaction();
+ VersionedNode parentGet = ( VersionedNode ) s.get( parent.getClass(), parent.getId() );
+ s.merge( parent );
+ s.getTransaction().commit();
+ s.close();
+
+ assertUpdateCount( 0 );
+ assertInsertCount( 0 );
+ clearCounts();
+
+ s = openSession();
+ s.beginTransaction();
+ VersionedNode parentLoad = ( VersionedNode ) s.load( parent.getClass(), parent.getId() );
+ s.merge( parent );
+ s.getTransaction().commit();
+ s.close();
+
+ assertUpdateCount( 0 );
+ assertInsertCount( 0 );
+ clearCounts();
+
+ s = openSession();
+ s.beginTransaction();
+ parent = ( VersionedNode ) s.get( VersionedNode.class, parent.getId() );
+ child = ( VersionedNode ) s.get( VersionedNode.class, child.getId() );
+ assertEquals( parent.getName(), "parent" );
+ assertEquals( 1, parent.getChildren().size() );
+ assertEquals( 0, parent.getVersion() );
+ assertSame( parent, child.getParent() );
+ assertSame( child, parent.getChildren().iterator().next() );
+ assertEquals( 0, child.getVersion() );
+ s.delete( parent );
+ s.delete( child );
+ s.getTransaction().commit();
+ s.close();
+
+ assertUpdateCount( 0 );
+ assertDeleteCount( 2 );
+ }
public void testAddNewParentToReadOnlyChild() throws Exception {
Session s = openSession();
@@ -448,9 +531,13 @@ public class ReadOnlyVersionedNodesTest extends FunctionalTestCase {
assertEquals( 0, child.getVersion() );
parent = ( VersionedNode ) s.get( VersionedNode.class, parent.getId() );
assertNull( parent );
+ s.setReadOnly( child, true );
s.delete( child );
s.getTransaction().commit();
s.close();
+
+ assertUpdateCount( 0 );
+ assertDeleteCount( 1 );
}
public void testUpdateChildWithNewParentCommitWithReadOnlyChild() throws Exception {
@@ -476,6 +563,7 @@ public class ReadOnlyVersionedNodesTest extends FunctionalTestCase {
assertUpdateCount( 0 );
assertInsertCount( 1 );
+ clearCounts();
s = openSession();
s.beginTransaction();
@@ -487,10 +575,15 @@ public class ReadOnlyVersionedNodesTest extends FunctionalTestCase {
assertNotNull( parent );
assertEquals( 0, parent.getChildren().size() );
assertEquals( 0, parent.getVersion() );
+ s.setReadOnly( parent, true );
+ s.setReadOnly( child, true );
s.delete( parent );
s.delete( child );
s.getTransaction().commit();
s.close();
+
+ assertUpdateCount( 0 );
+ assertDeleteCount( 2 );
}
public void testMergeDetachedChildWithNewParentCommitWithReadOnlyChild() throws Exception {
@@ -516,6 +609,7 @@ public class ReadOnlyVersionedNodesTest extends FunctionalTestCase {
assertUpdateCount( 1 );
assertInsertCount( 1 );
+ clearCounts();
s = openSession();
s.beginTransaction();
@@ -527,10 +621,15 @@ public class ReadOnlyVersionedNodesTest extends FunctionalTestCase {
assertNotNull( parent );
assertEquals( 0, parent.getChildren().size() );
assertEquals( 1, parent.getVersion() ); // hmmm, why is was version updated?
+ s.setReadOnly( parent, true );
+ s.setReadOnly( child, true );
s.delete( parent );
s.delete( child );
s.getTransaction().commit();
s.close();
+
+ assertUpdateCount( 0 );
+ assertDeleteCount( 2 );
}
public void testGetChildMakeReadOnlyThenMergeDetachedChildWithNewParent() throws Exception {
@@ -558,6 +657,7 @@ public class ReadOnlyVersionedNodesTest extends FunctionalTestCase {
assertUpdateCount( 1 );
assertInsertCount( 1 );
+ clearCounts();
s = openSession();
s.beginTransaction();
@@ -569,10 +669,15 @@ public class ReadOnlyVersionedNodesTest extends FunctionalTestCase {
assertNotNull( parent );
assertEquals( 0, parent.getChildren().size() );
assertEquals( 1, parent.getVersion() ); // / hmmm, why is was version updated?
+ s.setReadOnly( parent, true );
+ s.setReadOnly( child, true );
s.delete( parent );
s.delete( child );
s.getTransaction().commit();
s.close();
+
+ assertUpdateCount( 0 );
+ assertDeleteCount( 2 );
}
protected void cleanupTest() throws Exception {
@@ -590,23 +695,4 @@ public class ReadOnlyVersionedNodesTest extends FunctionalTestCase {
s.getTransaction().commit();
s.close();
}
-
- protected void clearCounts() {
- getSessions().getStatistics().clear();
- }
-
- protected void assertInsertCount(int expected) {
- int inserts = ( int ) getSessions().getStatistics().getEntityInsertCount();
- assertEquals( "unexpected insert count", expected, inserts );
- }
-
- protected void assertUpdateCount(int expected) {
- int updates = ( int ) getSessions().getStatistics().getEntityUpdateCount();
- assertEquals( "unexpected update counts", expected, updates );
- }
-
- protected void assertDeleteCount(int expected) {
- int deletes = ( int ) getSessions().getStatistics().getEntityDeleteCount();
- assertEquals( "unexpected delete counts", expected, deletes );
- }
}
diff --git a/testsuite/src/test/java/org/hibernate/test/readonly/criteria/Student.java b/testsuite/src/test/java/org/hibernate/test/readonly/Student.java
similarity index 94%
rename from testsuite/src/test/java/org/hibernate/test/readonly/criteria/Student.java
rename to testsuite/src/test/java/org/hibernate/test/readonly/Student.java
index 6ccc16de3a..c0fff9eafb 100755
--- a/testsuite/src/test/java/org/hibernate/test/readonly/criteria/Student.java
+++ b/testsuite/src/test/java/org/hibernate/test/readonly/Student.java
@@ -1,5 +1,5 @@
//$Id: Student.java 9116 2006-01-23 21:21:01Z steveebersole $
-package org.hibernate.test.readonly.criteria;
+package org.hibernate.test.readonly;
import java.util.HashSet;
import java.util.Set;
diff --git a/testsuite/src/test/java/org/hibernate/test/readonly/criteria/StudentDTO.java b/testsuite/src/test/java/org/hibernate/test/readonly/StudentDTO.java
similarity index 86%
rename from testsuite/src/test/java/org/hibernate/test/readonly/criteria/StudentDTO.java
rename to testsuite/src/test/java/org/hibernate/test/readonly/StudentDTO.java
index f645fb1d8a..746f7e3166 100644
--- a/testsuite/src/test/java/org/hibernate/test/readonly/criteria/StudentDTO.java
+++ b/testsuite/src/test/java/org/hibernate/test/readonly/StudentDTO.java
@@ -2,7 +2,7 @@
* Created on 28-Jan-2005
*
*/
-package org.hibernate.test.readonly.criteria;
+package org.hibernate.test.readonly;
/**
* @author max