Force a version check when merging an unchanged detached entity to ensure that

we don't blindly use stale state.



git-svn-id: https://svn.apache.org/repos/asf/incubator/openjpa/trunk@492790 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
A. Abram White 2007-01-04 22:44:19 +00:00
parent f5e4742f17
commit 663fbe62e3
2 changed files with 119 additions and 3 deletions

View File

@ -110,9 +110,9 @@ public class DetachedStateManager
FieldMetaData[] fields = meta.getFields();
int restore = broker.getRestoreState();
if (_dirty.length() > 0) {
BitSet load = (BitSet) _dirty.clone();
BitSet load = new BitSet(fields.length);
for (int i = 0; i < fields.length; i++) {
if (!load.get(i))
if (!_dirty.get(i))
continue;
switch (fields[i].getDeclaredTypeCode()) {
@ -140,7 +140,8 @@ public class DetachedStateManager
}
FetchConfiguration fc = broker.getFetchConfiguration();
sm.loadFields(load, fc, fc.getWriteLockLevel(), null, true);
}
}
Object origVersion = sm.getVersion();
sm.setVersion(_version);
BitSet loaded = sm.getLoaded();
@ -269,6 +270,17 @@ public class DetachedStateManager
}
}
pc.pcReplaceStateManager(sm);
// if we were clean at least make sure a version check is done to
// prevent using old state
if (!sm.isVersionCheckRequired() && broker.isActive()
&& _version != origVersion && (origVersion == null
|| broker.getStoreManager().compareVersion(sm, _version,
origVersion) != StoreManager.VERSION_SAME)) {
broker.transactional(sm.getManagedInstance(), false,
manager.getBehavior());
}
return sm.getManagedInstance();
}

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.detachment;
import java.util.HashMap;
import java.util.Map;
import javax.persistence.EntityManager;
import javax.persistence.EntityManagerFactory;
import javax.persistence.OptimisticLockException;
import javax.persistence.Persistence;
import junit.framework.TestCase;
import junit.textui.TestRunner;
/**
* Test that attaching an instance without having changed it still overwrites
* any changes to the managed copy.
*
* @author Abe White
*/
public class TestAttachWithNoChanges
extends TestCase {
private EntityManagerFactory emf;
public void setUp() {
String types = DetachmentOneManyParent.class.getName() + ";"
+ DetachmentOneManyChild.class.getName();
Map props = new HashMap();
props.put("openjpa.MetaDataFactory", "jpa(Types=" + types + ")");
emf = Persistence.createEntityManagerFactory("test", props);
}
public void tearDown() {
if (emf == null)
return;
try {
EntityManager em = emf.createEntityManager();
em.getTransaction().begin();
em.createQuery("delete from DetachmentOneManyChild").
executeUpdate();
em.createQuery("delete from DetachmentOneManyParent").
executeUpdate();
em.getTransaction().commit();
em.close();
emf.close();
} catch (Exception e) {
}
}
public void testAttachWithNoChangesChecksVersion() {
try {
DetachmentOneManyChild e = new DetachmentOneManyChild();
DetachmentOneManyParent p = new DetachmentOneManyParent();
e.setName("orig");
p.addChild(e);
EntityManager em = emf.createEntityManager();
em.getTransaction().begin();
em.persist(p);
em.persist(e);
em.flush();
em.clear();
DetachmentOneManyChild changed = em.find(DetachmentOneManyChild.class,
e.getId());
changed.setName("newname");
em.flush();
em.merge(e);
try {
em.flush();
fail("Should not be able to flush old version over new.");
} catch (OptimisticLockException ole) {
// expected
} finally {
if (em.getTransaction().isActive())
em.getTransaction().rollback();
em.close();
}
} catch (RuntimeException re) {
re.printStackTrace();
throw re;
}
}
public static void main(String[] args) {
TestRunner.run(TestAttachWithNoChanges.class);
}
}