OPENJPA-119. Needed to allow the EM.clear operation to perform without doing an implicit flush. Introduced a new boolean

parameter to indicate whether a flush is desired or not.  This allows both the new (correct) behaviour for JPA as well as the 
old behaviour for other persistence personalities (JDO, etc).  I also introduced a new testcase for this scenario, and updated 
a couple of other tests.

git-svn-id: https://svn.apache.org/repos/asf/incubator/openjpa/trunk@502751 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
Kevin W. Sutter 2007-02-02 21:12:35 +00:00
parent 9b78cd5441
commit d826caf711
8 changed files with 136 additions and 24 deletions

View File

@ -287,6 +287,8 @@ public abstract class AbstractBrokerFactory
Broker broker; Broker broker;
for (Iterator itr = _brokers.iterator(); itr.hasNext();) { for (Iterator itr = _brokers.iterator(); itr.hasNext();) {
broker = (Broker) itr.next(); broker = (Broker) itr.next();
/* Check for null here because _brokers is a weak reference
collection */
if ((broker != null) && (!broker.isClosed())) if ((broker != null) && (!broker.isClosed()))
broker.close(); broker.close();
} }

View File

@ -473,10 +473,21 @@ public interface Broker
public void evictAll(Extent extent, OpCallbacks call); public void evictAll(Extent extent, OpCallbacks call);
/** /**
* Detach all objects in place. * Detach all objects in place. A flush will be performed before
* detaching the entities.
*/ */
public void detachAll(OpCallbacks call); public void detachAll(OpCallbacks call);
/**
* Detach all objects in place, with the option of performing a
* flush before doing the detachment.
* @param call Persistence operation callbacks
* @param flush boolean value to indicate whether to perform a
* flush before detaching the entities (true, do the flush;
* false, don't do the flush)
*/
public void detachAll(OpCallbacks call, boolean flush);
/** /**
* Detach the specified object from the broker. * Detach the specified object from the broker.
* *

View File

@ -3088,9 +3088,16 @@ public class BrokerImpl
} }
public void detachAll(OpCallbacks call) { public void detachAll(OpCallbacks call) {
detachAll(call, true);
}
public void detachAll(OpCallbacks call, boolean flush) {
beginOperation(true); beginOperation(true);
try { try {
if ((_flags & FLAG_FLUSH_REQUIRED) != 0) /* If a flush is desired (based on input parm), then check if the
* "dirty" flag is set before calling flush().
*/
if ((flush) && ((_flags & FLAG_FLUSH_REQUIRED) != 0))
flush(); flush();
detachAllInternal(call); detachAllInternal(call);
} catch (OpenJPAException ke) { } catch (OpenJPAException ke) {

View File

@ -1115,6 +1115,14 @@ public class DelegatingBroker
} }
} }
public void detachAll(OpCallbacks call, boolean flush) {
try {
_broker.detachAll(call, flush);
} catch (RuntimeException re) {
throw translate(re);
}
}
public Object attach(Object obj, boolean copyNew, OpCallbacks call) { public Object attach(Object obj, boolean copyNew, OpCallbacks call) {
try { try {
return _broker.attach(obj, copyNew, call); return _broker.attach(obj, copyNew, call);

View File

@ -0,0 +1,104 @@
/*
* Copyright 2006 The Apache Software Foundation.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.openjpa.persistence.simple;
import java.util.HashMap;
import java.util.Map;
import javax.persistence.EntityManager;
import javax.persistence.EntityManagerFactory;
import javax.persistence.Persistence;
import junit.framework.TestCase;
import junit.textui.TestRunner;
/**
* Test case to ensure that the proper JPA clear semantics are processed.
*
* @author Kevin Sutter
*/
public class TestEntityManagerClear
extends TestCase {
private EntityManagerFactory emf;
private EntityManager em;
public void setUp() {
Map props = new HashMap(System.getProperties());
props.put("openjpa.MetaDataFactory",
"jpa(Types=" + AllFieldTypes.class.getName() + ")");
emf = Persistence.createEntityManagerFactory("test", props);
}
public void tearDown() {
if (emf == null)
return;
try {
EntityManager em = emf.createEntityManager();
em.getTransaction().begin();
em.createQuery("delete from AllFieldTypes").executeUpdate();
em.getTransaction().commit();
em.close();
emf.close();
} catch (Exception e) {
}
}
public void testClear() {
try {
// Create EntityManager and Start a transaction (1)
em = emf.createEntityManager();
em.getTransaction().begin();
// Insert a new object and flush
AllFieldTypes testObject1 = new AllFieldTypes();
testObject1.setStringField("my test object1");
em.persist(testObject1);
em.flush();
// Clear the PC for new object 2
AllFieldTypes testObject2 = new AllFieldTypes();
testObject1.setStringField("my test object2");
em.persist(testObject2);
em.clear();
// Commit the transaction (only object 1 should be in database)
em.getTransaction().commit();
// Start a new transaction
em.getTransaction().begin();
// Attempt retrieve of Object1 from previous PC (should exist)
assertEquals(1, em.createQuery
("select x from AllFieldTypes x where x.stringField = 'my test object1'").
getResultList().size());
// Attempt retrieve of Object2 from previous PC (should not exist)
assertEquals(0, em.createQuery
("select x from AllFieldTypes x where x.stringField = 'my test object2'").
getResultList().size());
// Rollback the transaction and close everything
em.getTransaction().rollback();
em.close();
} catch (Exception ex) {
fail("Unexpected Exception ex = " + ex);
}
}
public static void main(String[] args) {
TestRunner.run(TestEntityManagerClear.class);
}
}

View File

@ -271,7 +271,7 @@ public class TestEntityManagerMethodsThrowAfterClose
} }
public static void main(String[] args) { public static void main(String[] args) {
TestRunner.run(TestPersistence.class); TestRunner.run(TestEntityManagerMethodsThrowAfterClose.class);
} }
} }

View File

@ -107,26 +107,6 @@ public class TestPersistence
em.close(); em.close();
} }
/**
* Ensures that an IllegalStateException is thrown if getDelegate is called
* after closing the EntityManager.
*/
public void testGetDelegateAfterClose() {
EntityManager em = emf.createEntityManager();
em.close();
try {
Object o = em.getDelegate();
fail();
}
catch(IllegalStateException ise) {
/*
* An IllegalStateException is expected. Nothing to do here.
*/
}
}
public static void main(String[] args) { public static void main(String[] args) {
TestRunner.run(TestPersistence.class); TestRunner.run(TestPersistence.class);
} }

View File

@ -853,7 +853,7 @@ public class EntityManagerImpl
public void clear() { public void clear() {
assertNotCloseInvoked(); assertNotCloseInvoked();
_broker.detachAll(this); _broker.detachAll(this, false);
} }
public Object getDelegate() { public Object getDelegate() {