Author: gbadner
Date: 2009-12-23 13:38:09 -0500 (Wed, 23 Dec 2009)
New Revision: 18320
Modified:
core/trunk/core/src/main/java/org/hibernate/proxy/AbstractLazyInitializer.java
core/trunk/testsuite/src/test/java/org/hibernate/test/nonflushedchanges/SaveOrUpdateTest.java
core/trunk/testsuite/src/test/java/org/hibernate/test/ops/SaveOrUpdateTest.java
Log:
HHH-4735 : Proxy can be associated with a new session when it is already connected to a
different one
Modified: core/trunk/core/src/main/java/org/hibernate/proxy/AbstractLazyInitializer.java
===================================================================
---
core/trunk/core/src/main/java/org/hibernate/proxy/AbstractLazyInitializer.java 2009-12-23
10:57:37 UTC (rev 18319)
+++
core/trunk/core/src/main/java/org/hibernate/proxy/AbstractLazyInitializer.java 2009-12-23
18:38:09 UTC (rev 18320)
@@ -46,6 +46,7 @@
private boolean unwrap;
private transient SessionImplementor session;
+ private transient EntityKey entityKey; // cached value
/**
* For serialization from the non-pojo initializers (HHH-3309)
@@ -64,6 +65,7 @@
this.entityName = entityName;
this.id = id;
this.session = session;
+ this.entityKey = generateEntityKeyOrNull();
}
/**
@@ -85,6 +87,7 @@
*/
public final void setIdentifier(Serializable id) {
this.id = id;
+ entityKey = generateEntityKeyOrNull();
}
/**
@@ -110,17 +113,31 @@
//TODO: perhaps this should be some other RuntimeException...
throw new HibernateException("illegally attempted to associate a proxy with two
open Sessions");
}
+ else if ( s == null ){
+ unsetSession();
+ }
else {
session = s;
+ entityKey = generateEntityKeyOrNull();
}
}
}
+ private EntityKey generateEntityKeyOrNull() {
+ if ( getIdentifier() == null || session == null || entityName == null ) {
+ return null;
+ }
+ return new EntityKey(
+ getIdentifier(), session.getFactory().getEntityPersister( entityName ),
session.getEntityMode()
+ );
+ }
+
/**
* {@inheritDoc}
*/
public void unsetSession() {
session = null;
+ entityKey = null;
}
/**
@@ -162,11 +179,16 @@
* @return Value for property 'connectedToSession'.
*/
protected final boolean isConnectedToSession() {
- return session!=null &&
- session.isOpen() &&
- session.getPersistenceContext().containsProxy(this);
+ return getProxyOrNull() != null;
}
+ private Object getProxyOrNull() {
+ if ( session != null && session.isOpen() && entityKey != null ) {
+ return session.getPersistenceContext().getProxy( entityKey );
+ }
+ return null;
+ }
+
/**
* Return the underlying persistent object, initializing if necessary
*/
Modified:
core/trunk/testsuite/src/test/java/org/hibernate/test/nonflushedchanges/SaveOrUpdateTest.java
===================================================================
---
core/trunk/testsuite/src/test/java/org/hibernate/test/nonflushedchanges/SaveOrUpdateTest.java 2009-12-23
10:57:37 UTC (rev 18319)
+++
core/trunk/testsuite/src/test/java/org/hibernate/test/nonflushedchanges/SaveOrUpdateTest.java 2009-12-23
18:38:09 UTC (rev 18320)
@@ -5,6 +5,7 @@
import org.hibernate.Hibernate;
import org.hibernate.Session;
+import org.hibernate.HibernateException;
import org.hibernate.cfg.Configuration;
import org.hibernate.cfg.Environment;
import org.hibernate.criterion.Projections;
@@ -441,7 +442,24 @@
SimpleJtaTransactionManagerImpl.getInstance().begin();
Session s2 = openSession();
- s2.saveOrUpdate( child );
+ try {
+ s2.getTransaction().begin();
+ s2.saveOrUpdate( child );
+ fail();
+ }
+ catch ( HibernateException ex ) {
+ // expected because parent is connected to s1
+ }
+ finally {
+ SimpleJtaTransactionManagerImpl.getInstance().rollback();
+ }
+
+ s1.evict( child.getParent() );
+ assertFalse( s1.contains( child.getParent() ) );
+
+ SimpleJtaTransactionManagerImpl.getInstance().begin();
+ s2 = openSession();
+ s2.saveOrUpdate( child );
s2 = applyNonFlushedChangesToNewSessionCloseOldSession( s2 );
child = ( Node ) getOldToNewEntityRefMap().get( child );
assertTrue( s2.contains( child ) );
Modified: core/trunk/testsuite/src/test/java/org/hibernate/test/ops/SaveOrUpdateTest.java
===================================================================
---
core/trunk/testsuite/src/test/java/org/hibernate/test/ops/SaveOrUpdateTest.java 2009-12-23
10:57:37 UTC (rev 18319)
+++
core/trunk/testsuite/src/test/java/org/hibernate/test/ops/SaveOrUpdateTest.java 2009-12-23
18:38:09 UTC (rev 18320)
@@ -6,6 +6,7 @@
import org.hibernate.Hibernate;
import org.hibernate.Session;
import org.hibernate.Transaction;
+import org.hibernate.HibernateException;
import org.hibernate.junit.functional.FunctionalTestCase;
import org.hibernate.junit.functional.FunctionalTestClassTestSuite;
import org.hibernate.intercept.FieldInterceptionHelper;
@@ -388,6 +389,23 @@
assertTrue( s1.contains( child.getParent() ) );
Session s2 = openSession();
+ try {
+ s2.getTransaction().begin();
+ s2.saveOrUpdate( child );
+ fail();
+ }
+ catch ( HibernateException ex ) {
+ // expected because parent is connected to s1
+ }
+ finally {
+ s2.getTransaction().rollback();
+ }
+ s2.close();
+
+ s1.evict( child.getParent() );
+ assertFalse( s1.contains( child.getParent() ) );
+
+ s2 = openSession();
s2.getTransaction().begin();
s2.saveOrUpdate( child );
assertTrue( s2.contains( child ) );