From: <hib...@li...> - 2006-07-20 19:20:13
|
Author: ste...@jb... Date: 2006-07-20 15:19:21 -0400 (Thu, 20 Jul 2006) New Revision: 10127 Added: trunk/Hibernate3/test/org/hibernate/test/ops/OptLockEntity.hbm.xml trunk/Hibernate3/test/org/hibernate/test/ops/TimestampedEntity.java trunk/Hibernate3/test/org/hibernate/test/ops/VersionedEntity.java Modified: trunk/Hibernate3/src/org/hibernate/event/def/AbstractSaveEventListener.java trunk/Hibernate3/src/org/hibernate/event/def/DefaultMergeEventListener.java trunk/Hibernate3/test/org/hibernate/test/ops/MergeTest.java Log: HHH-1927 : persist() and merge() in same txn Modified: trunk/Hibernate3/src/org/hibernate/event/def/AbstractSaveEventListener.java =================================================================== --- trunk/Hibernate3/src/org/hibernate/event/def/AbstractSaveEventListener.java 2006-07-20 17:27:30 UTC (rev 10126) +++ trunk/Hibernate3/src/org/hibernate/event/def/AbstractSaveEventListener.java 2006-07-20 19:19:21 UTC (rev 10127) @@ -451,12 +451,29 @@ Object entity, String entityName, EntityEntry entry, //pass this as an argument only to avoid double looking - SessionImplementor source - ) { - - if ( entry!=null ) { // the object is persistent - - //the entity is associated with the session, so check its status + SessionImplementor source) { + + if ( entry == null && performDeepStateChecking() ) { + // check to handle fringe case of merging the same "entity data" via + // a transient instance within the same transaction it was saved; i.e.: + // Session s = ...; + // s.beginTransaction(); + // s.persist( new Entity( "someid" ) ); + // s.merge( new Entity( "someid" ) ); + // s.getTransaction().commit(); + EntityPersister persister = source.getEntityPersister( entityName, entity ); + Serializable id = persister.getIdentifier( entity, source.getEntityMode() ); + if ( id != null ) { + EntityKey key = new EntityKey( id, persister, source.getEntityMode() ); + entry = source.getPersistenceContext().getEntry( + source.getPersistenceContext().getEntity( key ) + ); + } + } + + if ( entry != null ) { + // the object is persistent as it has an entry associated with the + // session; so check its status if ( entry.getStatus() != Status.DELETED ) { // do nothing for persistent instances if ( log.isTraceEnabled() ) { @@ -479,11 +496,10 @@ } } - else { // the object is transient or detached - - //the entity is not associated with the session, so - //try interceptor and unsaved-value - + else { + // the entity is not associated with the session, so the various + // unsaved-value algorithms to determine whether it is transient + // or detached if ( ForeignKeys.isTransient( entityName, entity, getAssumedUnsaved(), source ) ) { if ( log.isTraceEnabled() ) { log.trace( @@ -514,4 +530,7 @@ return null; } + protected boolean performDeepStateChecking() { + return false; + } } Modified: trunk/Hibernate3/src/org/hibernate/event/def/DefaultMergeEventListener.java =================================================================== --- trunk/Hibernate3/src/org/hibernate/event/def/DefaultMergeEventListener.java 2006-07-20 17:27:30 UTC (rev 10126) +++ trunk/Hibernate3/src/org/hibernate/event/def/DefaultMergeEventListener.java 2006-07-20 19:19:21 UTC (rev 10127) @@ -116,7 +116,11 @@ } } - + + protected boolean performDeepStateChecking() { + return true; + } + protected void entityIsPersistent(MergeEvent event, Map copyCache) { log.trace("ignoring persistent instance"); Modified: trunk/Hibernate3/test/org/hibernate/test/ops/MergeTest.java =================================================================== --- trunk/Hibernate3/test/org/hibernate/test/ops/MergeTest.java 2006-07-20 17:27:30 UTC (rev 10126) +++ trunk/Hibernate3/test/org/hibernate/test/ops/MergeTest.java 2006-07-20 19:19:21 UTC (rev 10127) @@ -2,6 +2,7 @@ package org.hibernate.test.ops; import java.util.ArrayList; +import java.util.Date; import junit.framework.Test; import junit.framework.TestSuite; @@ -9,6 +10,7 @@ import org.hibernate.Hibernate; import org.hibernate.Session; import org.hibernate.Transaction; +import org.hibernate.NonUniqueObjectException; import org.hibernate.cfg.Configuration; import org.hibernate.cfg.Environment; import org.hibernate.criterion.Projections; @@ -22,7 +24,59 @@ public MergeTest(String str) { super(str); } - + + public void testPersistThenMergeInSameTxnWithVersion() { + Session s = openSession(); + Transaction tx = s.beginTransaction(); + VersionedEntity entity = new VersionedEntity( "test", "test" ); + s.persist( entity ); + s.merge( new VersionedEntity( "test", "test-2" ) ); + + try { + // control operation... + s.saveOrUpdate( new VersionedEntity( "test", "test-3" ) ); + fail( "saveOrUpdate() should fail here" ); + } + catch( NonUniqueObjectException expected ) { + // expected behavior + } + + tx.commit(); + s.close(); + + s = openSession(); + tx = s.beginTransaction(); + s.delete( entity ); + tx.commit(); + s.close(); + } + + public void testPersistThenMergeInSameTxnWithTimestamp() { + Session s = openSession(); + Transaction tx = s.beginTransaction(); + TimestampedEntity entity = new TimestampedEntity( "test", "test" ); + s.persist( entity ); + s.merge( new TimestampedEntity( "test", "test-2" ) ); + + try { + // control operation... + s.saveOrUpdate( new TimestampedEntity( "test", "test-3" ) ); + fail( "saveOrUpdate() should fail here" ); + } + catch( NonUniqueObjectException expected ) { + // expected behavior + } + + tx.commit(); + s.close(); + + s = openSession(); + tx = s.beginTransaction(); + s.delete( entity ); + tx.commit(); + s.close(); + } + public void testMergeDeepTree() { clearCounts(); @@ -330,7 +384,7 @@ } protected String[] getMappings() { - return new String[] { "ops/Node.hbm.xml", "ops/Employer.hbm.xml" }; + return new String[] { "ops/Node.hbm.xml", "ops/Employer.hbm.xml", "ops/OptLockEntity.hbm.xml" }; } public static Test suite() { Added: trunk/Hibernate3/test/org/hibernate/test/ops/OptLockEntity.hbm.xml =================================================================== --- trunk/Hibernate3/test/org/hibernate/test/ops/OptLockEntity.hbm.xml 2006-07-20 17:27:30 UTC (rev 10126) +++ trunk/Hibernate3/test/org/hibernate/test/ops/OptLockEntity.hbm.xml 2006-07-20 19:19:21 UTC (rev 10127) @@ -0,0 +1,29 @@ +<?xml version="1.0"?> +<!DOCTYPE hibernate-mapping PUBLIC + "-//Hibernate/Hibernate Mapping DTD 3.0//EN" + "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd"> + +<!-- + +--> + +<hibernate-mapping package="org.hibernate.test.ops"> + + <class name="VersionedEntity" table="V_ENTITY"> + <id name="id" column="ID" type="string"> + <generator class="assigned"/> + </id> + <version name="version" column="VERS" type="long" /> + <property name="name" column="NAME" type="string" /> + </class> + + <class name="TimestampedEntity" table="T_ENTITY"> + <id name="id" column="ID" type="string"> + <generator class="assigned"/> + </id> + <timestamp name="timestamp" column="TS" /> + <property name="name" column="NAME" type="string" /> + </class> + +</hibernate-mapping> + Added: trunk/Hibernate3/test/org/hibernate/test/ops/TimestampedEntity.java =================================================================== --- trunk/Hibernate3/test/org/hibernate/test/ops/TimestampedEntity.java 2006-07-20 17:27:30 UTC (rev 10126) +++ trunk/Hibernate3/test/org/hibernate/test/ops/TimestampedEntity.java 2006-07-20 19:19:21 UTC (rev 10127) @@ -0,0 +1,47 @@ +package org.hibernate.test.ops; + +import java.util.Date; + +/** + * todo: describe TimestampedEntity + * + * @author Steve Ebersole + */ +public class TimestampedEntity { + private String id; + private String name; + private Date timestamp; + + public TimestampedEntity() { + } + + public TimestampedEntity(String id, String name) { + this.id = id; + this.name = name; + } + + public String getId() { + return id; + } + + public void setId(String id) { + this.id = id; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public Date getTimestamp() { + return timestamp; + } + + public void setTimestamp(Date timestamp) { + this.timestamp = timestamp; + } +} + Added: trunk/Hibernate3/test/org/hibernate/test/ops/VersionedEntity.java =================================================================== --- trunk/Hibernate3/test/org/hibernate/test/ops/VersionedEntity.java 2006-07-20 17:27:30 UTC (rev 10126) +++ trunk/Hibernate3/test/org/hibernate/test/ops/VersionedEntity.java 2006-07-20 19:19:21 UTC (rev 10127) @@ -0,0 +1,44 @@ +package org.hibernate.test.ops; + +/** + * todo: describe VersionedEntity + * + * @author Steve Ebersole + */ +public class VersionedEntity { + private String id; + private String name; + private long version; + + public VersionedEntity() { + } + + public VersionedEntity(String id, String name) { + this.id = id; + this.name = name; + } + + public String getId() { + return id; + } + + public void setId(String id) { + this.id = id; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public long getVersion() { + return version; + } + + public void setVersion(long version) { + this.version = version; + } +} |