|
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;
+ }
+}
|