Author: jrbauer
Date: Mon Feb 6 22:03:02 2012
New Revision: 1241207
URL: http://svn.apache.org/viewvc?rev=1241207&view=rev
Log:
OPENJPA-2120 Add option for optimizing copy operations for qualifying id
classes.
Added:
openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/enhance/ids/
openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/enhance/ids/Device.java
(with props)
openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/enhance/ids/DeviceId.java
(with props)
openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/enhance/ids/Hardware.java
(with props)
openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/enhance/ids/HardwareId.java
(with props)
openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/enhance/ids/Software.java
(with props)
openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/enhance/ids/SoftwareId.java
(with props)
openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/enhance/ids/TestOptimizeIdCopy.java
(with props)
openjpa/trunk/openjpa-persistence-jdbc/src/test/resources/META-INF/optidcpy_persistence.xml
(with props)
Modified:
openjpa/trunk/openjpa-kernel/src/main/java/org/apache/openjpa/conf/OpenJPAConfiguration.java
openjpa/trunk/openjpa-kernel/src/main/java/org/apache/openjpa/conf/OpenJPAConfigurationImpl.java
openjpa/trunk/openjpa-kernel/src/main/java/org/apache/openjpa/enhance/PCEnhancer.java
openjpa/trunk/openjpa-kernel/src/main/java/org/apache/openjpa/util/ApplicationIds.java
openjpa/trunk/openjpa-persistence-jdbc/src/main/ant/enhancer.xml
Modified:
openjpa/trunk/openjpa-kernel/src/main/java/org/apache/openjpa/conf/OpenJPAConfiguration.java
URL:
http://svn.apache.org/viewvc/openjpa/trunk/openjpa-kernel/src/main/java/org/apache/openjpa/conf/OpenJPAConfiguration.java?rev=1241207&r1=1241206&r2=1241207&view=diff
==============================================================================
---
openjpa/trunk/openjpa-kernel/src/main/java/org/apache/openjpa/conf/OpenJPAConfiguration.java
(original)
+++
openjpa/trunk/openjpa-kernel/src/main/java/org/apache/openjpa/conf/OpenJPAConfiguration.java
Mon Feb 6 22:03:02 2012
@@ -1918,5 +1918,37 @@ public interface OpenJPAConfiguration
*/
public void setPostLoadOnMerge(Boolean postLoadOnMerge);
+ /**
+ * Whether to attempt to optimize id class copy operations during the
+ * enhancement process. Optimization is only applicable for simple id
classes
+ * that have a constructor with the proper construction parameters and
+ * direct assignments to fields within the id class during construction.
+ * If the optimization cannot occur, the enhancer will fallback to the
+ * noraml behavior.
+ * @since 2.2.0
+ */
+ public boolean getOptimizeIdCopy();
+
+ /**
+ * Whether to attempt to optimize id class copy operations during the
+ * enhancement process. Optimization is only applicable for simple id
classes
+ * that have a constructor with the proper construction parameters and
+ * direct assignments to fields within the id class during construction.
+ * If the optimization cannot occur, the enhancer will fallback to the
+ * normal behavior.
+ * @since 2.2.0
+ */
+ public void setOptimizeIdCopy(boolean optimizeIds);
+
+ /**
+ * Whether to attempt to optimize id class copy operations during the
+ * enhancement process. Optimization is only applicable for simple id
classes
+ * that have a constructor with the proper construction parameters and
+ * direct assignments to fields within the id class during construction.
+ * If the optimization cannot occur, the enhancer will fallback to the
+ * normal behavior.
+ * @since 2.2.0
+ */
+ public void setOptimizeIdCopy(Boolean optimizeIds);
}
Modified:
openjpa/trunk/openjpa-kernel/src/main/java/org/apache/openjpa/conf/OpenJPAConfigurationImpl.java
URL:
http://svn.apache.org/viewvc/openjpa/trunk/openjpa-kernel/src/main/java/org/apache/openjpa/conf/OpenJPAConfigurationImpl.java?rev=1241207&r1=1241206&r2=1241207&view=diff
==============================================================================
---
openjpa/trunk/openjpa-kernel/src/main/java/org/apache/openjpa/conf/OpenJPAConfigurationImpl.java
(original)
+++
openjpa/trunk/openjpa-kernel/src/main/java/org/apache/openjpa/conf/OpenJPAConfigurationImpl.java
Mon Feb 6 22:03:02 2012
@@ -177,6 +177,7 @@ public class OpenJPAConfigurationImpl
public ObjectValue instrumentationManager;
public PluginListValue instrumentationProviders;
public BooleanValue postLoadOnMerge;
+ public BooleanValue optimizeIdCopy;
// custom values
public BrokerFactoryValue brokerFactoryPlugin;
@@ -402,6 +403,10 @@ public class OpenJPAConfigurationImpl
postLoadOnMerge.setDefault("false");
postLoadOnMerge.set(false);
+ optimizeIdCopy = addBoolean("OptimizeIdCopy");
+ optimizeIdCopy.setDefault("false");
+ optimizeIdCopy.set(false);
+
autoClear = addInt("AutoClear");
aliases =
new String[] { "datastore",
@@ -1856,5 +1861,18 @@ public class OpenJPAConfigurationImpl
setPostLoadOnMerge(postLoadOnMerge.booleanValue());
}
+ public boolean getOptimizeIdCopy() {
+ return optimizeIdCopy.get();
+ }
+
+ public void setOptimizeIdCopy(boolean optimizeId) {
+ optimizeIdCopy.set(optimizeId);
+ }
+
+ public void setOptimizeIdCopy(Boolean optimizeId) {
+ if (optimizeId != null) {
+ setOptimizeIdCopy(optimizeId.booleanValue());
+ }
+ }
}
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=1241207&r1=1241206&r2=1241207&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
Mon Feb 6 22:03:02 2012
@@ -69,6 +69,7 @@ import org.apache.openjpa.meta.FieldMeta
import org.apache.openjpa.meta.JavaTypes;
import org.apache.openjpa.meta.MetaDataRepository;
import org.apache.openjpa.meta.ValueStrategies;
+import org.apache.openjpa.util.ApplicationIds;
import org.apache.openjpa.util.GeneralException;
import org.apache.openjpa.util.InternalException;
import org.apache.openjpa.util.BigDecimalId;
@@ -102,6 +103,7 @@ import serp.bytecode.LoadInstruction;
import serp.bytecode.LookupSwitchInstruction;
import serp.bytecode.MethodInstruction;
import serp.bytecode.Project;
+import serp.bytecode.PutFieldInstruction;
import serp.bytecode.TableSwitchInstruction;
import serp.bytecode.ClassInstruction;
import serp.util.Strings;
@@ -212,6 +214,8 @@ public class PCEnhancer {
private boolean _isAlreadySubclassed = false;
private boolean _bcsConfigured = false;
+ private boolean _optimizeIdCopy = false; // whether to attempt optimizing
id copy
+
/**
* Constructor. Supply configuration and type to enhance. This will look
* up the metadata for <code>type</code> from <code>conf</code>'s
@@ -280,6 +284,8 @@ public class PCEnhancer {
} else
_repos = repos;
_meta = _repos.getMetaData(type.getType(), loader, false);
+
+ configureOptimizeIdCopy();
}
/**
@@ -2010,11 +2016,52 @@ public class PCEnhancer {
// id.<field> = pc.<field>;
FieldMetaData[] fmds = getCreateSubclass() ? _meta.getFields()
: _meta.getDeclaredFields();
- Class type;
+ Class<?> type;
String name;
Field field;
Method setter;
boolean reflect;
+ // If optimizeIdCopy is enabled and not a field manager method, try to
+ // optimize the copyTo by using a public constructor instead of
reflection
+ if (_optimizeIdCopy && !fieldManager) {
+ ArrayList<Integer> pkfields = optimizeIdCopy(oidType, fmds);
+ if (pkfields != null) {
+ // search for a constructor on the IdClass that can be used
+ // to construct the IdClass
+ int parmOrder[] = getIdClassConstructorParmOrder(oidType,
pkfields, fmds);
+ if (parmOrder != null) {
+ // found a matching constructor. parm array is
constructor parm order
+ code.anew().setType(oidType);
+ code.dup();
+ // build the parm list in order
+ Class<?>[] clsArgs = new Class<?>[parmOrder.length];
+ for (int i = 0; i < clsArgs.length; i++) {
+ int parmIndex = parmOrder[i];
+ clsArgs[i] = fmds[parmIndex].getObjectIdFieldType();
+ loadManagedInstance(code, false);
+ addGetManagedValueCode(code, fmds[parmIndex]);
+ }
+ // invoke the public constructor to create a new local id
+ code.invokespecial().setMethod(oidType, "<init>",
void.class, clsArgs);
+ int ret = code.getNextLocalsIndex();
+ code.astore().setLocal(ret);
+
+ // swap out the app id with the new one
+ code.aload().setLocal(1);
+ code.checkcast().setType(ObjectId.class);
+ code.aload().setLocal(ret);
+ code.invokestatic().setMethod(ApplicationIds.class,
+ "setAppId", void.class, new Class[] {
ObjectId.class,
+ Object.class });
+ code.vreturn();
+
+ code.calculateMaxStack();
+ code.calculateMaxLocals();
+ return;
+ }
+ }
+ }
+
for (int i = 0; i < fmds.length; i++) {
if (!fmds[i].isPrimaryKey())
continue;
@@ -2428,17 +2475,28 @@ public class PCEnhancer {
if (Modifier.isPublic(field.getModifiers()))
code.getfield().setField(field);
else {
- // Reflection.getXXX(oid, Reflection.findField(...));
- code.classconstant().setClass(oidType);
- code.constant().setValue(name);
- code.constant().setValue(true);
- code.invokestatic().setMethod(Reflection.class,
- "findField", Field.class, new Class[] {
- Class.class, String.class, boolean.class });
- code.invokestatic().setMethod
- (getReflectionGetterMethod(type, Field.class));
- if (!type.isPrimitive() && type != Object.class)
- code.checkcast().setType(type);
+ boolean usedFastOid = false;
+ if (_optimizeIdCopy) {
+ // If fastOids, ignore access type and try to use
a public getter
+ getter = Reflection.findGetter(oidType, name,
false);
+ if (getter != null &&
Modifier.isPublic(getter.getModifiers())) {
+ usedFastOid = true;
+ code.invokevirtual().setMethod(getter);
+ }
+ }
+ if (!usedFastOid) {
+ // Reflection.getXXX(oid,
Reflection.findField(...));
+ code.classconstant().setClass(oidType);
+ code.constant().setValue(name);
+ code.constant().setValue(true);
+ code.invokestatic().setMethod(Reflection.class,
+ "findField", Field.class, new Class[] {
+ Class.class, String.class, boolean.class });
+ code.invokestatic().setMethod
+ (getReflectionGetterMethod(type, Field.class));
+ if (!type.isPrimitive() && type != Object.class)
+ code.checkcast().setType(type);
+ }
}
} else {
getter = Reflection.findGetter(oidType, name, true);
@@ -4823,4 +4881,116 @@ public class PCEnhancer {
}
return false;
}
+
+ /**
+ * Read the optimizedIdCopy value from the config (if available)
+ */
+ private void configureOptimizeIdCopy() {
+ if (_repos != null && _repos.getConfiguration() != null) {
+ _optimizeIdCopy = _repos.getConfiguration().getOptimizeIdCopy();
+ }
+ }
+
+ /*
+ * Cycles through all primary keys verifying whether they can and should
+ * be used for faster oid copy. The field must be private and must
+ * not have a public setter. If this is the case, the list of pk fields is
+ * returned. If not, returns null.
+ */
+ private ArrayList<Integer> optimizeIdCopy(Class<?> oidType,
FieldMetaData[] fmds) {
+ // collect all object id fields and verify they
+ // a) have a private field
+ // b) do not have a public setter
+ ArrayList<Integer> pkFields = new ArrayList<Integer>();
+ // build list of primary key fields
+ for (int i = 0; i < fmds.length; i++) {
+ if (!fmds[i].isPrimaryKey())
+ continue;
+ // optimizing copy with PC type not (yet) supported
+ if (fmds[i].getDeclaredTypeCode() == JavaTypes.PC) {
+ return null;
+ }
+ String name = fmds[i].getName();
+ Field fld = Reflection.findField(oidType, name, false);
+ if (fld == null || Modifier.isPublic(fld.getModifiers())) {
+ return null;
+ }
+ Method setter = Reflection.findSetter(oidType, name, false);
+ if (setter == null || !Modifier.isPublic(setter.getModifiers())) {
+ pkFields.add(i);
+ } else {
+ return null;
+ }
+ }
+ return pkFields.size() > 0 ? pkFields : null;
+ }
+
+ /*
+ * Cycles through all constructors of an IdClass and examines the
instructions to find
+ * a matching constructor for the provided pk fields. If a match is
found, it returns
+ * the order (relative to the field metadata) of the constructor
parameters. If a match
+ * is not found, returns null.
+ */
+ private int[] getIdClassConstructorParmOrder(Class<?> oidType,
ArrayList<Integer> pkfields,
+ FieldMetaData[] fmds) {
+ Project project = new Project();
+ BCClass bc = project.loadClass(oidType);
+ BCMethod[] methods = bc.getDeclaredMethods("<init>");
+ if (methods == null || methods.length == 0) {
+ return null;
+ }
+
+ int parmOrder[] = new int[pkfields.size()];
+ for (BCMethod method : methods) {
+ // constructor must be public
+ if (!method.isPublic()) {
+ continue;
+ }
+ Class<?>[] parmTypes = method.getParamTypes();
+ // make sure the constructors have the same # of parms as
+ // the number of pk fields
+ if (parmTypes.length != pkfields.size()) {
+ continue;
+ }
+
+ int parmOrderIndex = 0;
+ Code code = method.getCode(false);
+ Instruction[] ins = code.getInstructions();
+ for (int i = 0; i < ins.length; i++) {
+ if (ins[i] instanceof PutFieldInstruction) {
+ PutFieldInstruction pfi = (PutFieldInstruction)ins[i];
+ for (int j = 0; j < pkfields.size(); j++) {
+ int fieldNum = pkfields.get(j);
+ // Compare the field being set with the current pk
field
+ String parmName = fmds[fieldNum].getName();
+ Class<?> parmType = fmds[fieldNum].getType();
+ if (parmName.equals(pfi.getFieldName())) {
+ // backup and examine the load instruction parm
+ if (i > 0 && ins[i-1] instanceof LoadInstruction) {
+ LoadInstruction li = (LoadInstruction)ins[i-1];
+ // Get the local index from the instruction.
This will be the index
+ // of the constructor parameter. must be less
than or equal to the
+ // max parm index to prevent from picking up
locals that could have
+ // been produced within the constructor. Also
make sure the parm type
+ // matches the fmd type
+ int parm = li.getLocal();
+ if (parm <= pkfields.size() &&
parmTypes[parm-1].equals(parmType)) {
+ parmOrder[parmOrderIndex] = fieldNum;
+ parmOrderIndex++;
+ }
+ } else {
+ // Some other instruction found. can't make a
determination of which local/parm
+ // is being used on the putfield.
+ break;
+ }
+ }
+ }
+ }
+ }
+ if (parmOrderIndex == pkfields.size()) {
+ return parmOrder;
+ }
+ }
+ return null;
+ }
}
Modified:
openjpa/trunk/openjpa-kernel/src/main/java/org/apache/openjpa/util/ApplicationIds.java
URL:
http://svn.apache.org/viewvc/openjpa/trunk/openjpa-kernel/src/main/java/org/apache/openjpa/util/ApplicationIds.java?rev=1241207&r1=1241206&r2=1241207&view=diff
==============================================================================
---
openjpa/trunk/openjpa-kernel/src/main/java/org/apache/openjpa/util/ApplicationIds.java
(original)
+++
openjpa/trunk/openjpa-kernel/src/main/java/org/apache/openjpa/util/ApplicationIds.java
Mon Feb 6 22:03:02 2012
@@ -576,6 +576,14 @@ public class ApplicationIds {
}
/**
+ * Sets the underlying id of an ObjectId. Should only
+ * be used with simple (idclass) types.
+ */
+ public static void setAppId(ObjectId id, Object newId) {
+ id.setId(newId);
+ }
+
+ /**
* Helper class used to transfer pk values to/from application oids.
*/
private static class PrimaryKeyFieldManager
Modified: openjpa/trunk/openjpa-persistence-jdbc/src/main/ant/enhancer.xml
URL:
http://svn.apache.org/viewvc/openjpa/trunk/openjpa-persistence-jdbc/src/main/ant/enhancer.xml?rev=1241207&r1=1241206&r2=1241207&view=diff
==============================================================================
--- openjpa/trunk/openjpa-persistence-jdbc/src/main/ant/enhancer.xml (original)
+++ openjpa/trunk/openjpa-persistence-jdbc/src/main/ant/enhancer.xml Mon Feb 6
22:03:02 2012
@@ -31,12 +31,12 @@
<istrue value="${maven.test.skip}" />
</condition>
- <condition property="skip.enhance">
- <or>
+ <condition property="skip.enhance">
+ <or>
<equals arg1="${test}" arg2="false" />
- <equals arg1="${build.enhance}" arg2="false" />
- <istrue value="${maven.test.skip}" />
- <istrue value="${skipTests}" />
+ <equals arg1="${build.enhance}" arg2="false" />
+ <istrue value="${maven.test.skip}" />
+ <istrue value="${skipTests}" />
</or>
</condition>
@@ -83,7 +83,8 @@
<exclude name="org/apache/openjpa/enhance/EnhancedSubClass.class"/>
<exclude name="**/AbstractUnenhanced*.class" />
<exclude name="**/unenhanced/*.class" />
- <exclude
name="**/persistence/property/AccessModsEntity.class"/>
+ <exclude name="**/persistence/property/AccessModsEntity.class"/>
+ <exclude name="org/apache/openjpa/enhance/ids/*.class"/>
</fileset>
<openjpac>
<classpath refid="cp" />
@@ -99,17 +100,17 @@
<include name="**/detach/serializable/*.class" />
<!-- include files from orm.xml -->
<include name="**/xml/*.class" />
- <exclude
name="**/persistence/delimited/identifiers/xml/*.class"/>
+ <exclude
name="**/persistence/delimited/identifiers/xml/*.class"/>
<exclude name="**/Test*.class" />
</fileset>
<config log="${openjpa.Log}" />
</openjpac>
- <!-- Enhance with private persistent properties compatibility
option -->
+ <!-- Enhance with private persistent properties compatibility option
-->
<openjpac>
<config
propertiesFile="${project.build.testOutputDirectory}/META-INF/nopriv_persistence.xml"
/>
<classpath refid="cp" />
<fileset dir="${project.build.testOutputDirectory}">
- <include
name="**/persistence/property/AccessModsEntity.class"/>
+ <include name="**/persistence/property/AccessModsEntity.class"/>
</fileset>
<config log="${openjpa.Log}" />
</openjpac>
@@ -132,15 +133,24 @@
</fileset>
<config log="${openjpa.Log}" />
</openjpac>
- <!-- Enhance delimited identifiers XML-based entities
separately -->
+ <!-- Enhance delimited identifiers XML-based entities separately -->
<openjpac>
<config
propertiesFile="${project.build.testOutputDirectory}/META-INF/delim_persistence.xml"
/>
<classpath refid="cp" />
<fileset dir="${project.build.testOutputDirectory}">
- <include
name="**/persistence/delimited/identifiers/xml/*.class"/>
- <exclude
name="**/persistence/delimited/identifiers/xml/Test*.class"/>
+ <include
name="**/persistence/delimited/identifiers/xml/*.class"/>
+ <exclude
name="**/persistence/delimited/identifiers/xml/Test*.class"/>
</fileset>
<config log="${openjpa.Log}"/>
</openjpac>
+ <!-- Enhance with optimized id copy option -->
+ <openjpac>
+ <config
propertiesFile="${project.build.testOutputDirectory}/META-INF/optidcpy_persistence.xml"
/>
+ <classpath refid="cp" />
+ <fileset dir="${project.build.testOutputDirectory}">
+ <include name="org/apache/openjpa/enhance/ids/*.class"/>
+ </fileset>
+ <config log="${openjpa.Log}" />
+ </openjpac>
</target>
</project>
Added:
openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/enhance/ids/Device.java
URL:
http://svn.apache.org/viewvc/openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/enhance/ids/Device.java?rev=1241207&view=auto
==============================================================================
---
openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/enhance/ids/Device.java
(added)
+++
openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/enhance/ids/Device.java
Mon Feb 6 22:03:02 2012
@@ -0,0 +1,70 @@
+/*
+ * 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.enhance.ids;
+
+import javax.persistence.Column;
+import javax.persistence.Entity;
+import javax.persistence.Id;
+import javax.persistence.IdClass;
+import javax.persistence.Table;
+
+@Entity
+@Table(name="ID_DEVTBL")
+@IdClass(DeviceId.class)
+public class Device {
+
+ @Id
+ @Column(name="DEV_ID")
+ private int id;
+
+ @Id
+ @Column(name="DEV_TYPE")
+ private int type;
+
+ @Column(name="DEV_DESC")
+ private String description;
+
+ public Device() {
+
+ }
+
+ public void setId(int id) {
+ this.id = id;
+ }
+
+ public int getId() {
+ return id;
+ }
+
+ public void setType(int type) {
+ this.type = type;
+ }
+
+ public int getType() {
+ return type;
+ }
+
+ public void setDescription(String description) {
+ this.description = description;
+ }
+
+ public String getDescription() {
+ return description;
+ }
+}
Propchange:
openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/enhance/ids/Device.java
------------------------------------------------------------------------------
svn:eol-style = native
Added:
openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/enhance/ids/DeviceId.java
URL:
http://svn.apache.org/viewvc/openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/enhance/ids/DeviceId.java?rev=1241207&view=auto
==============================================================================
---
openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/enhance/ids/DeviceId.java
(added)
+++
openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/enhance/ids/DeviceId.java
Mon Feb 6 22:03:02 2012
@@ -0,0 +1,67 @@
+/*
+ * 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.enhance.ids;
+
+public class DeviceId {
+
+ public static boolean[] usedConstructor = new boolean[3];
+
+ private int id;
+
+ private int type;
+
+ public DeviceId() {
+ usedConstructor[0] = true;
+ }
+
+ @SuppressWarnings("unused")
+ private DeviceId(int i, int t) {
+ usedConstructor[1] = true;
+ id = i;
+ type = t;
+ }
+
+ public DeviceId(int i) {
+ usedConstructor[2] = true;
+ id = i;
+ }
+
+ public int getId() {
+ return id;
+ }
+
+ public int getType() {
+ return type;
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (obj instanceof DeviceId) {
+ DeviceId did = (DeviceId)obj;
+ return did.getId() == getId() &&
+ did.getType() == getType();
+ }
+ return false;
+ }
+
+ @Override
+ public int hashCode() {
+ return getId() + getType();
+ }
+}
Propchange:
openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/enhance/ids/DeviceId.java
------------------------------------------------------------------------------
svn:eol-style = native
Added:
openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/enhance/ids/Hardware.java
URL:
http://svn.apache.org/viewvc/openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/enhance/ids/Hardware.java?rev=1241207&view=auto
==============================================================================
---
openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/enhance/ids/Hardware.java
(added)
+++
openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/enhance/ids/Hardware.java
Mon Feb 6 22:03:02 2012
@@ -0,0 +1,65 @@
+/*
+ * 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.enhance.ids;
+
+import javax.persistence.Entity;
+import javax.persistence.Id;
+import javax.persistence.IdClass;
+import javax.persistence.Table;
+
+@Table(name="ID_HWTBL")
+@IdClass(HardwareId.class)
+@Entity
+public class Hardware {
+
+ @Id
+ private String serial;
+
+ @Id
+ private String model;
+
+ private String description;
+
+ public Hardware() {
+ }
+
+ public void setSerial(String serial) {
+ this.serial = serial;
+ }
+
+ public String getSerial() {
+ return serial;
+ }
+
+ public void setModel(String model) {
+ this.model = model;
+ }
+
+ public String getModel() {
+ return model;
+ }
+
+ public void setDescription(String description) {
+ this.description = description;
+ }
+
+ public String getDescription() {
+ return description;
+ }
+}
Propchange:
openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/enhance/ids/Hardware.java
------------------------------------------------------------------------------
svn:eol-style = native
Added:
openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/enhance/ids/HardwareId.java
URL:
http://svn.apache.org/viewvc/openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/enhance/ids/HardwareId.java?rev=1241207&view=auto
==============================================================================
---
openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/enhance/ids/HardwareId.java
(added)
+++
openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/enhance/ids/HardwareId.java
Mon Feb 6 22:03:02 2012
@@ -0,0 +1,67 @@
+/*
+ * 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.enhance.ids;
+
+public class HardwareId {
+
+ public static boolean[] usedConstructor = new boolean[2];
+
+ private String serial;
+
+ private String model;
+
+ public HardwareId() {
+ }
+
+ // Parms out of order
+ public HardwareId(String model, String serial) {
+ usedConstructor[0] = true;
+ this.serial = serial;
+ this.model = model;
+ }
+
+ public HardwareId(String model,int serial) {
+ usedConstructor[1] = true;
+ this.model = model;
+ this.serial = Integer.toString(serial);
+ }
+
+ public String getSerial() {
+ return serial;
+ }
+
+ public String getModel() {
+ return model;
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (obj instanceof HardwareId) {
+ HardwareId hid = (HardwareId)obj;
+ return hid.getModel().equals(getModel()) &&
+ hid.getSerial().equals(getSerial());
+ }
+ return false;
+ }
+
+ @Override
+ public int hashCode() {
+ return getSerial().hashCode() + getModel().hashCode();
+ }
+}
Propchange:
openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/enhance/ids/HardwareId.java
------------------------------------------------------------------------------
svn:eol-style = native
Added:
openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/enhance/ids/Software.java
URL:
http://svn.apache.org/viewvc/openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/enhance/ids/Software.java?rev=1241207&view=auto
==============================================================================
---
openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/enhance/ids/Software.java
(added)
+++
openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/enhance/ids/Software.java
Mon Feb 6 22:03:02 2012
@@ -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.enhance.ids;
+
+import javax.persistence.Entity;
+import javax.persistence.Id;
+import javax.persistence.IdClass;
+import javax.persistence.Table;
+
+@Entity
+@Table(name="ID_SWTBL")
+@IdClass(SoftwareId.class)
+public class Software {
+
+ @Id
+ private Integer idInteger;
+
+ @Id
+ private int idInt;
+
+ @Id
+ private String idString;
+
+ public Software() {
+
+ }
+
+ public void setIdInteger(Integer idInteger) {
+ this.idInteger = idInteger;
+ }
+
+ public Integer getIdInteger() {
+ return idInteger;
+ }
+
+ public void setIdInt(int idInt) {
+ this.idInt = idInt;
+ }
+
+ public int getIdInt() {
+ return idInt;
+ }
+
+ public void setIdString(String idString) {
+ this.idString = idString;
+ }
+
+ public String getIdString() {
+ return idString;
+ }
+
+}
Propchange:
openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/enhance/ids/Software.java
------------------------------------------------------------------------------
svn:eol-style = native
Added:
openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/enhance/ids/SoftwareId.java
URL:
http://svn.apache.org/viewvc/openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/enhance/ids/SoftwareId.java?rev=1241207&view=auto
==============================================================================
---
openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/enhance/ids/SoftwareId.java
(added)
+++
openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/enhance/ids/SoftwareId.java
Mon Feb 6 22:03:02 2012
@@ -0,0 +1,80 @@
+/*
+ * 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.enhance.ids;
+
+public class SoftwareId {
+
+ public static boolean[] usedConstructor = new boolean[3];
+
+ private Integer idInteger;
+
+ private int idInt;
+
+ private String idString;
+
+ public SoftwareId() {
+
+ }
+
+ public SoftwareId(int idint) {
+ usedConstructor[0] = true;
+ idInt = idint;
+ }
+
+ public SoftwareId(Integer idinteger, int idint) {
+ usedConstructor[1] = true;
+ idInteger = idinteger;
+ idInt = idint;
+ }
+
+ public SoftwareId(Integer idinteger, int idint, String idstring) {
+ usedConstructor[2] = true;
+ idInteger = idinteger;
+ idInt = idint;
+ idString =idstring;
+ }
+ public Integer getIdInteger() {
+ return idInteger;
+ }
+
+ public int getIdInt() {
+ return idInt;
+ }
+
+ public String getIdString() {
+ return idString;
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (obj instanceof SoftwareId) {
+ SoftwareId swid = (SoftwareId)obj;
+ return swid.getIdInt() == getIdInt() &&
+ swid.getIdInteger().equals(getIdInteger()) &&
+ swid.getIdString().equals(getIdString());
+ }
+ return false;
+ }
+
+ @Override
+ public int hashCode() {
+ return getIdInt() + getIdInteger().hashCode() +
getIdString().hashCode();
+ }
+
+}
Propchange:
openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/enhance/ids/SoftwareId.java
------------------------------------------------------------------------------
svn:eol-style = native
Added:
openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/enhance/ids/TestOptimizeIdCopy.java
URL:
http://svn.apache.org/viewvc/openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/enhance/ids/TestOptimizeIdCopy.java?rev=1241207&view=auto
==============================================================================
---
openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/enhance/ids/TestOptimizeIdCopy.java
(added)
+++
openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/enhance/ids/TestOptimizeIdCopy.java
Mon Feb 6 22:03:02 2012
@@ -0,0 +1,122 @@
+/*
+ * 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.enhance.ids;
+
+import java.util.List;
+import java.util.Random;
+
+import javax.persistence.EntityManager;
+import javax.persistence.TypedQuery;
+
+import org.apache.openjpa.persistence.test.SingleEMFTestCase;
+
+/**
+ * Verifies the use of the openjpa.OptimizeIdCopy configuration parameter.
This parameter
+ * changes the behavior of the enhancer and thus, must be set before
enhancement occurs. There
+ * is special enhancement task in main/ant/enhancer.xml to ensure this value
is set
+ * during the enhancement process for the entities used by this test.
+ */
+public class TestOptimizeIdCopy extends SingleEMFTestCase {
+
+ @Override
+ public void setUp() {
+ setUp(Device.class,Hardware.class,Software.class, CLEAR_TABLES);
+ }
+
+ /*
+ * Verifies that constructor-based Id optimization occurs during Id copy.
Asserts
+ * only the proper/expected public constructor is called during the id
copy operation.
+ */
+ public void testIdOptimization() {
+ EntityManager em = emf.createEntityManager();
+
+ // Add a software entity
+ Software sw = new Software();
+ int id = new Random().nextInt();
+ sw.setIdInt(id);
+ sw.setIdInteger(10);
+ sw.setIdString("StringIdVal");
+
+ em.getTransaction().begin();
+ em.persist(sw);
+ em.getTransaction().commit();
+ em.clear();
+
+ TypedQuery<Software> swq = em.createQuery("select sw from Software
sw", Software.class);
+ List<Software> swl = swq.getResultList();
+ assertTrue("Software result list > 0", swl.size() > 0);
+ // Id copy optimization should have used the 3rd constructor
+ assertFalse("First constructor was not used",
SoftwareId.usedConstructor[0]);
+ assertFalse("Second constructor was not used",
SoftwareId.usedConstructor[1]);
+ assertTrue("Third (correct) constructor was used",
SoftwareId.usedConstructor[2]);
+ em.close();
+ }
+
+ /*
+ * Verifies that constructor based optimization functions even if parms
+ * are different than field order
+ */
+ public void testIdOptimizationConstructorOutOfOrder() {
+ EntityManager em = emf.createEntityManager();
+
+ Hardware hw = new Hardware();
+ String id = "Model" + (new Random().nextInt());
+ hw.setModel("Model" + id);
+ hw.setSerial("123XYZ");
+
+ em.getTransaction().begin();
+ em.persist(hw);
+ em.getTransaction().commit();
+ em.clear();
+
+ TypedQuery<Hardware> hwq = em.createQuery("select hw from Hardware
hw", Hardware.class);
+ List<Hardware> hwl = hwq.getResultList();
+ assertTrue("Hardware result list > 0", hwl.size() > 0);
+ // Id copy optimization should have used the first constructor
+ assertTrue("First (correct) constructor was used",
HardwareId.usedConstructor[0]);
+ assertFalse("Second constructor was not used",
HardwareId.usedConstructor[1]);
+ em.close();
+ }
+
+ /*
+ * Verifies that classes without a proper constructor do not get optimized
+ */
+ public void testNoOptimization() {
+ EntityManager em = emf.createEntityManager();
+
+ int id = new Random().nextInt();
+ Device d = new Device();
+ d.setId(id);
+ d.setType(10);
+
+ em.getTransaction().begin();
+ em.persist(d);
+ em.getTransaction().commit();
+ em.clear();
+
+ TypedQuery<Device> dq = em.createQuery("select d from Device d",
Device.class);
+ List<Device> dl = dq.getResultList();
+ assertTrue("Device result list > 0", dl.size() > 0);
+ // Only the first, default constructor should have been called
+ assertTrue("First (default) constructor was used",
DeviceId.usedConstructor[0]);
+ assertFalse("Second constructor was not used",
DeviceId.usedConstructor[1]);
+ assertFalse("Third constructor was not used",
DeviceId.usedConstructor[2]);
+ em.close();
+ }
+}
Propchange:
openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/enhance/ids/TestOptimizeIdCopy.java
------------------------------------------------------------------------------
svn:eol-style = native
Added:
openjpa/trunk/openjpa-persistence-jdbc/src/test/resources/META-INF/optidcpy_persistence.xml
URL:
http://svn.apache.org/viewvc/openjpa/trunk/openjpa-persistence-jdbc/src/test/resources/META-INF/optidcpy_persistence.xml?rev=1241207&view=auto
==============================================================================
---
openjpa/trunk/openjpa-persistence-jdbc/src/test/resources/META-INF/optidcpy_persistence.xml
(added)
+++
openjpa/trunk/openjpa-persistence-jdbc/src/test/resources/META-INF/optidcpy_persistence.xml
Mon Feb 6 22:03:02 2012
@@ -0,0 +1,38 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ 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.
+-->
+<persistence
+ xmlns="http://java.sun.com/xml/ns/persistence"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://java.sun.com/xml/ns/persistence
+ http://java.sun.com/xml/ns/persistence/persistence_2_0.xsd"
+ version="2.0" >
+
+ <persistence-unit name="OptimizeIdCopy_PU">
+ <description>
+ This PU
+ </description>
+ <class>org.apache.openjpa.enhance.ids.Device</class>
+ <class>org.apache.openjpa.enhance.ids.Hardware</class>
+ <class>org.apache.openjpa.enhance.ids.Software</class>
+ <properties>
+ <property name="openjpa.OptimizeIdCopy" value="true"/>
+ </properties>
+ </persistence-unit>
+</persistence>
\ No newline at end of file
Propchange:
openjpa/trunk/openjpa-persistence-jdbc/src/test/resources/META-INF/optidcpy_persistence.xml
------------------------------------------------------------------------------
svn:eol-style = native