You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@openjpa.apache.org by cu...@apache.org on 2010/12/22 19:41:10 UTC
svn commit: r1052025 - in /openjpa/trunk:
openjpa-kernel/src/main/java/org/apache/openjpa/enhance/
openjpa-kernel/src/main/java/org/apache/openjpa/kernel/
openjpa-kernel/src/main/java/org/apache/openjpa/meta/
openjpa-kernel/src/test/java/org/apache/ope...
Author: curtisr7
Date: Wed Dec 22 18:41:09 2010
New Revision: 1052025
URL: http://svn.apache.org/viewvc?rev=1052025&view=rev
Log:
OPENJPA-1896: Allow merging a StateManagerless Entity with a default primitive version.
Added:
openjpa/trunk/openjpa-kernel/src/test/java/org/apache/openjpa/meta/TestJavaTypes.java (with props)
openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/detach/IntegerVersionEntity.java (with props)
openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/detach/TestMergeNoStateManager.java (with props)
Modified:
openjpa/trunk/openjpa-kernel/src/main/java/org/apache/openjpa/enhance/PCEnhancer.java
openjpa/trunk/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/VersionAttachStrategy.java
openjpa/trunk/openjpa-kernel/src/main/java/org/apache/openjpa/meta/JavaTypes.java
openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/detach/IntVersionEntity.java
Modified: openjpa/trunk/openjpa-kernel/src/main/java/org/apache/openjpa/enhance/PCEnhancer.java
URL: http://svn.apache.org/viewvc/openjpa/trunk/openjpa-kernel/src/main/java/org/apache/openjpa/enhance/PCEnhancer.java?rev=1052025&r1=1052024&r2=1052025&view=diff
==============================================================================
--- openjpa/trunk/openjpa-kernel/src/main/java/org/apache/openjpa/enhance/PCEnhancer.java (original)
+++ openjpa/trunk/openjpa-kernel/src/main/java/org/apache/openjpa/enhance/PCEnhancer.java Wed Dec 22 18:41:09 2010
@@ -3261,15 +3261,14 @@ public class PCEnhancer {
ifins.setTarget(code.nop());
// if (pcVersionInit != false)
// return true
- // else return false;
+ // else return null; // (returning null because we don't know the correct answer)
loadManagedInstance(code, false);
getfield(code, null, VERSION_INIT_STR);
ifins = code.ifeq();
code.getstatic().setField(Boolean.class, "TRUE", Boolean.class);
code.areturn();
ifins.setTarget(code.nop());
- code.getstatic().setField(Boolean.class, "FALSE", Boolean.class);
-
+ code.constant().setNull();
}
code.areturn();
return false;
Modified: openjpa/trunk/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/VersionAttachStrategy.java
URL: http://svn.apache.org/viewvc/openjpa/trunk/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/VersionAttachStrategy.java?rev=1052025&r1=1052024&r2=1052025&view=diff
==============================================================================
--- openjpa/trunk/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/VersionAttachStrategy.java (original)
+++ openjpa/trunk/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/VersionAttachStrategy.java Wed Dec 22 18:41:09 2010
@@ -18,12 +18,15 @@
*/
package org.apache.openjpa.kernel;
+import java.lang.reflect.Field;
import java.util.Collection;
import java.util.Iterator;
import java.util.Map;
import org.apache.openjpa.enhance.PersistenceCapable;
+import org.apache.openjpa.enhance.Reflection;
import org.apache.openjpa.enhance.StateManager;
+import org.apache.openjpa.event.LifecycleEvent;
import org.apache.openjpa.lib.util.Localizer;
import org.apache.openjpa.meta.ClassMetaData;
import org.apache.openjpa.meta.FieldMetaData;
@@ -31,10 +34,9 @@ import org.apache.openjpa.meta.JavaTypes
import org.apache.openjpa.meta.ValueMetaData;
import org.apache.openjpa.meta.ValueStrategies;
import org.apache.openjpa.util.ApplicationIds;
+import org.apache.openjpa.util.ImplHelper;
import org.apache.openjpa.util.ObjectNotFoundException;
import org.apache.openjpa.util.OptimisticException;
-import org.apache.openjpa.util.ImplHelper;
-import org.apache.openjpa.event.LifecycleEvent;
/**
* Handles attaching instances using version and primary key fields.
@@ -175,9 +177,29 @@ class VersionAttachStrategy
*/
private void compareVersion(StateManagerImpl sm, PersistenceCapable pc) {
Object version = pc.pcGetVersion();
- if (version == null)
+ // In the event that the version field is a primitive and it is the types default value, we can't differentiate
+ // between a value that was set to be the default, and one that defaulted to that value.
+ if (version != null
+ && JavaTypes.isPrimitiveDefault(version, sm.getMetaData().getVersionField().getTypeCode())) {
+ Field pcVersionInitField = null;
+ try {
+ pcVersionInitField = pc.getClass().getDeclaredField("pcVersionInit");
+ Object pcField = Reflection.get(pc, pcVersionInitField);
+ if (pcField != null) {
+ boolean bool = (Boolean) pcField;
+ if (bool == false) {
+ // If this field if false, that means that the pcGetVersion returned a default value rather than
+ // and actual value.
+ version = null;
+ }
+ }
+ } catch (Exception e) {
+ // Perhaps this is an Entity that was enhanced before the pcVersionInit field was added.
+ }
+ }
+ if (version == null) {
return;
-
+ }
// don't need to load unloaded fields since its implicitly
// a single field value
StoreManager store = sm.getBroker().getStoreManager();
Modified: openjpa/trunk/openjpa-kernel/src/main/java/org/apache/openjpa/meta/JavaTypes.java
URL: http://svn.apache.org/viewvc/openjpa/trunk/openjpa-kernel/src/main/java/org/apache/openjpa/meta/JavaTypes.java?rev=1052025&r1=1052024&r2=1052025&view=diff
==============================================================================
--- openjpa/trunk/openjpa-kernel/src/main/java/org/apache/openjpa/meta/JavaTypes.java (original)
+++ openjpa/trunk/openjpa-kernel/src/main/java/org/apache/openjpa/meta/JavaTypes.java Wed Dec 22 18:41:09 2010
@@ -435,4 +435,31 @@ public class JavaTypes {
Array.set(array, idx, itr.next ());
return array;
}
+
+ /**
+ * Determine whether or not the provided Object value is the default for the provided typeCode.
+ *
+ * For example: If o = Integer(0) and typeCode = JavaTypes.INT, this method will return true.
+ */
+ public static boolean isPrimitiveDefault(Object o, int typeCode) {
+ switch (typeCode) {
+ case BOOLEAN:
+ return ((Boolean) o).equals(Boolean.FALSE) ? true : false;
+ case BYTE:
+ return ((Byte) o) == 0 ? true : false;
+ case SHORT:
+ return ((Short) o) == 0 ? true : false;
+ case INT:
+ return ((Integer) o) == 0 ? true : false;
+ case LONG:
+ return ((Long) o) == 0L ? true : false;
+ case FLOAT:
+ return ((Float) o) == 0.0F ? true : false;
+ case CHAR:
+ return ((Character) o) == '\u0000' ? true : false;
+ case DOUBLE:
+ return ((Double) o) == 0.0d ? true : false;
+ }
+ return false;
+ }
}
Added: openjpa/trunk/openjpa-kernel/src/test/java/org/apache/openjpa/meta/TestJavaTypes.java
URL: http://svn.apache.org/viewvc/openjpa/trunk/openjpa-kernel/src/test/java/org/apache/openjpa/meta/TestJavaTypes.java?rev=1052025&view=auto
==============================================================================
--- openjpa/trunk/openjpa-kernel/src/test/java/org/apache/openjpa/meta/TestJavaTypes.java (added)
+++ openjpa/trunk/openjpa-kernel/src/test/java/org/apache/openjpa/meta/TestJavaTypes.java Wed Dec 22 18:41:09 2010
@@ -0,0 +1,68 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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.meta;
+
+import junit.framework.TestCase;
+
+public class TestJavaTypes extends TestCase {
+ TypesHolder _types = new TypesHolder();
+
+ public void testIsPrimitiveDefault() {
+ assertTrue(JavaTypes.isPrimitiveDefault(_types.getBoolean(), JavaTypes.BOOLEAN));
+ assertTrue(JavaTypes.isPrimitiveDefault(_types.getChar(), JavaTypes.CHAR));
+ assertTrue(JavaTypes.isPrimitiveDefault(_types.getDouble(), JavaTypes.DOUBLE));
+ assertTrue(JavaTypes.isPrimitiveDefault(_types.getInt(), JavaTypes.INT));
+ assertTrue(JavaTypes.isPrimitiveDefault(_types.getLong(), JavaTypes.LONG));
+ assertTrue(JavaTypes.isPrimitiveDefault(_types.getShort(), JavaTypes.SHORT));
+ }
+
+ class TypesHolder {
+ boolean _boolean;
+ short _short;
+ int _int;
+ long _long;
+ float _float;
+ double _double;
+ char _char;
+
+ public Object getBoolean() {
+ return _boolean;
+ }
+
+ public Object getShort() {
+ return _short;
+ }
+
+ public Object getInt() {
+ return _int;
+ }
+
+ public Object getLong() {
+ return _long;
+ }
+
+ public Object getDouble() {
+ return _double;
+ }
+
+ public Object getChar() {
+ return _char;
+ }
+ }
+}
Propchange: openjpa/trunk/openjpa-kernel/src/test/java/org/apache/openjpa/meta/TestJavaTypes.java
------------------------------------------------------------------------------
svn:eol-style = native
Modified: openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/detach/IntVersionEntity.java
URL: http://svn.apache.org/viewvc/openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/detach/IntVersionEntity.java?rev=1052025&r1=1052024&r2=1052025&view=diff
==============================================================================
--- openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/detach/IntVersionEntity.java (original)
+++ openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/detach/IntVersionEntity.java Wed Dec 22 18:41:09 2010
@@ -18,6 +18,8 @@
*/
package org.apache.openjpa.persistence.detach;
+import java.io.Serializable;
+
import javax.persistence.CascadeType;
import javax.persistence.Entity;
import javax.persistence.FetchType;
@@ -26,7 +28,7 @@ import javax.persistence.OneToOne;
import javax.persistence.Version;
@Entity
-public class IntVersionEntity {
+public class IntVersionEntity implements Serializable {
@Id
private int id;
Added: openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/detach/IntegerVersionEntity.java
URL: http://svn.apache.org/viewvc/openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/detach/IntegerVersionEntity.java?rev=1052025&view=auto
==============================================================================
--- openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/detach/IntegerVersionEntity.java (added)
+++ openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/detach/IntegerVersionEntity.java Wed Dec 22 18:41:09 2010
@@ -0,0 +1,58 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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.detach;
+
+import javax.persistence.Entity;
+import javax.persistence.Id;
+import javax.persistence.Version;
+
+@Entity
+public class IntegerVersionEntity {
+
+ @Id
+ private int id;
+ private String name;
+
+ @Version
+ private Integer version;
+
+ public int getVersion() {
+ return version;
+ }
+
+ public IntegerVersionEntity(int id) {
+ this.id = id;
+ }
+
+ public int getId() {
+ return id;
+ }
+
+ public void setId(int id) {
+ this.id = id;
+ }
+
+ public String getName() {
+ return name;
+ }
+
+ public void setName(String name) {
+ this.name = name;
+ }
+}
Propchange: openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/detach/IntegerVersionEntity.java
------------------------------------------------------------------------------
svn:eol-style = native
Added: openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/detach/TestMergeNoStateManager.java
URL: http://svn.apache.org/viewvc/openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/detach/TestMergeNoStateManager.java?rev=1052025&view=auto
==============================================================================
--- openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/detach/TestMergeNoStateManager.java (added)
+++ openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/detach/TestMergeNoStateManager.java Wed Dec 22 18:41:09 2010
@@ -0,0 +1,129 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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.detach;
+
+import javax.persistence.OptimisticLockException;
+
+import org.apache.openjpa.persistence.OpenJPAEntityManagerSPI;
+import org.apache.openjpa.persistence.test.SingleEMFTestCase;
+
+/**
+ * Added for OPENJPA-1896
+ */
+public class TestMergeNoStateManager extends SingleEMFTestCase {
+ Object[] args =
+ new Object[] { TimestampVersionEntity.class, IntVersionEntity.class, NoVersionEntity.class,
+ IntegerVersionEntity.class, CLEAR_TABLES, "openjpa.Log", "SQL=trace" };
+
+ IntVersionEntity _ive;
+ NoVersionEntity _nve;
+ IntegerVersionEntity _integerVe;
+
+ @Override
+ public void setUp() throws Exception {
+ super.setUp(args);
+ OpenJPAEntityManagerSPI em = emf.createEntityManager();
+ try {
+ if (em.find(IntVersionEntity.class, 1) == null) {
+ em.getTransaction().begin();
+ _ive = new IntVersionEntity(1);
+ _nve = new NoVersionEntity(1);
+ _integerVe = new IntegerVersionEntity(1);
+
+ em.persist(_ive);
+ em.persist(_nve);
+ em.persist(_integerVe);
+
+ em.getTransaction().commit();
+ }
+ } finally {
+ em.close();
+ }
+ }
+
+ /**
+ * This test is commented out is it will fail.
+ */
+// public void testOLE() throws Exception {
+// OpenJPAEntityManagerSPI em = emf.createEntityManager();
+// try {
+// String updatedName = "updatedName_" + System.currentTimeMillis();
+// IntVersionEntity ive = em.find(IntVersionEntity.class, _ive.getId());
+// em.clear();
+//
+// IntVersionEntity detachedIve = new IntVersionEntity(_ive.getId());
+// // Set the version to older than currently in the db to simulate having stale data
+// detachedIve.setId(0);
+// detachedIve.setName(updatedName);
+// // serialize
+// detachedIve = roundtrip(detachedIve);
+//
+// em.getTransaction().begin();
+// // This merge should throw an OLE since we have older version than current
+// try {
+// em.merge(detachedIve);
+// throw new RuntimeException("Expected an OLE, but didn't get one!");
+// } catch (OptimisticLockException ole) {
+// // expected
+// }
+// } finally {
+// if (em.getTransaction().isActive()) {
+// em.getTransaction().rollback();
+// }
+// em.close();
+// }
+// }
+
+ public void test() throws Exception {
+ OpenJPAEntityManagerSPI em = emf.createEntityManager();
+ try {
+ String updatedName = "updatedName_" + System.currentTimeMillis();
+ IntVersionEntity detachedIve = new IntVersionEntity(_ive.getId());
+ NoVersionEntity detachedNve = new NoVersionEntity(_nve.getId());
+ IntegerVersionEntity detachedIntegerVe = new IntegerVersionEntity(_integerVe.getId());
+
+ detachedIntegerVe.setName(updatedName);
+ detachedNve.setName(updatedName);
+ detachedIve.setName(updatedName);
+
+ em.getTransaction().begin();
+ em.merge(detachedIntegerVe);
+ em.merge(detachedNve);
+ em.merge(detachedIve);
+ em.getTransaction().commit();
+
+ em.clear();
+
+ detachedIntegerVe = em.find(IntegerVersionEntity.class, _integerVe.getId());
+ detachedNve = em.find(NoVersionEntity.class, _nve.getId());
+ detachedIve = em.find(IntVersionEntity.class, _ive.getId());
+
+ // Make sure the updated values were persisted
+ assertEquals(detachedIntegerVe.getName(), updatedName);
+ assertEquals(detachedNve.getName(), updatedName);
+ assertEquals(detachedIve.getName(), updatedName);
+
+ } finally {
+ if (em.getTransaction().isActive()) {
+ em.getTransaction().commit();
+ }
+ em.close();
+ }
+ }
+}
Propchange: openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/detach/TestMergeNoStateManager.java
------------------------------------------------------------------------------
svn:eol-style = native