Author: hthomann
Date: Fri Jun 24 03:31:13 2016
New Revision: 1750037
URL: http://svn.apache.org/viewvc?rev=1750037&view=rev
Log:
OPENJPA-2631: Fix for CriteriaBuilder issue with an @EmbeddedId that contains
more than one field. Ported 2.1.x commit to 2.2.x
Added:
openjpa/branches/2.2.x/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/embed/compositepk/
- copied from r1750036,
openjpa/branches/2.1.x/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/embed/compositepk/
Modified:
openjpa/branches/2.2.x/ (props changed)
openjpa/branches/2.2.x/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/exps/EqualExpression.java
openjpa/branches/2.2.x/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/exps/Lit.java
openjpa/branches/2.2.x/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/meta/ClassMapping.java
Propchange: openjpa/branches/2.2.x/
------------------------------------------------------------------------------
--- svn:mergeinfo (original)
+++ svn:mergeinfo Fri Jun 24 03:31:13 2016
@@ -1,5 +1,5 @@
/openjpa/branches/1.0.x:736493
/openjpa/branches/2.0.x:1484136,1484287,1504611
-/openjpa/branches/2.1.x:1415379,1415398,1469090,1469949,1484300,1484313,1485010,1505837,1513249,1517838,1529241,1530146,1533218,1533280,1539188,1569528,1575444,1591536,1614935,1636464,1648430,1655218,1662610,1673300,1673491,1686894,1709201,1709309
+/openjpa/branches/2.1.x:1415379,1415398,1469090,1469949,1484300,1484313,1485010,1505837,1513249,1517838,1529241,1530146,1533218,1533280,1539188,1569528,1575444,1591536,1614935,1636464,1648430,1655218,1662610,1673300,1673491,1686894,1709201,1709309,1750036
/openjpa/branches/2.2.1.x:1415367,1415413,1415425,1469408,1470097,1484320,1484322,1491895,1504719,1529267,1529340,1530347,1531176,1533222,1539193,1584153,1648450,1651808,1686910
/openjpa/trunk:1416742,1420324,1430117,1431649,1436957,1436960,1448662,1448796,1451369,1456574,1456614,1459091,1461833,1469646,1469649,1469652,1504282,1558594,1564989,1600682,1600757,1603251,1626287,1632647
Modified:
openjpa/branches/2.2.x/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/exps/EqualExpression.java
URL:
http://svn.apache.org/viewvc/openjpa/branches/2.2.x/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/exps/EqualExpression.java?rev=1750037&r1=1750036&r2=1750037&view=diff
==============================================================================
---
openjpa/branches/2.2.x/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/exps/EqualExpression.java
(original)
+++
openjpa/branches/2.2.x/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/exps/EqualExpression.java
Fri Jun 24 03:31:13 2016
@@ -18,6 +18,10 @@
*/
package org.apache.openjpa.jdbc.kernel.exps;
+import java.util.List;
+
+import org.apache.openjpa.jdbc.meta.ClassMapping;
+import org.apache.openjpa.jdbc.meta.FieldMapping;
import org.apache.openjpa.jdbc.sql.SQLBuffer;
import org.apache.openjpa.jdbc.sql.Select;
@@ -62,8 +66,31 @@ class EqualExpression
new FilterValueImpl(sel, ctx, bstate.state1, val1),
new FilterValueImpl(sel, ctx, bstate.state2, val2));
} else {
- int len = java.lang.Math.min(val1.length(sel, ctx,
- bstate.state1), val2.length(sel, ctx, bstate.state2));
+ int lenVal1 = val1.length(sel, ctx, bstate.state1);
+ int lenVal2 = val2.length(sel, ctx, bstate.state2);
+ int len = java.lang.Math.min(lenVal1, lenVal2);
+
+ // OPENJPA-2631: Detect and handle slightly differently the
+ // case where a composite PK is in use. When an equals
comparison
+ // is created by CriteriaBuilder, and the comparison is done
against
+ // an entity with a composite PK, 'val2' can be either a:
+ // 1) Lit - in this case a Lit is hard coded to return a
length of 1.
+ // 2) Param - in this case the metadata is null so length will
return 1.
+ // Given this, first look to see if lenVal1 is greater than
lenVal2.
+ if (lenVal1 > lenVal2) {
+ // If here, lets get the metadata from val1 and see if its
PK
+ // is an embeddable. If so, the length (val1Len) will be
the
+ // size of the number of colunns in the PK. Use this length
+ // in order to create an equal expression with the right
number
+ // of 'AND' statementes.
+ ClassMapping cm = (ClassMapping) val1.getMetaData();
+ FieldMapping[] fmsPK = cm.getPrimaryKeyFieldMappings();
+
+ if (fmsPK[0].isEmbedded()) {
+ len = lenVal1;
+ }
+ }
+
for (int i = 0; i < len; i++) {
if (i > 0)
buf.append(" AND ");
Modified:
openjpa/branches/2.2.x/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/exps/Lit.java
URL:
http://svn.apache.org/viewvc/openjpa/branches/2.2.x/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/exps/Lit.java?rev=1750037&r1=1750036&r2=1750037&view=diff
==============================================================================
---
openjpa/branches/2.2.x/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/exps/Lit.java
(original)
+++
openjpa/branches/2.2.x/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/exps/Lit.java
Fri Jun 24 03:31:13 2016
@@ -116,10 +116,11 @@ public class Lit
public void appendTo(Select sel, ExpContext ctx, ExpState state,
SQLBuffer sql, int index) {
LitExpState lstate = (LitExpState) state;
- if (lstate.otherLength > 1)
- sql.appendValue(((Object[]) lstate.sqlValue)[index],
- lstate.getColumn(index));
- else if (_isRaw) {
+ if (lstate.otherLength > 1) {
+ sql.appendValue(((Object[]) lstate.sqlValue)[index],
lstate.getColumn(index));
+ // OPENJPA-2631: Return so as not to go into sql.appendValue a
second time below.
+ return;
+ } else if (_isRaw) {
int parseType = getParseType();
if (parseType == Literal.TYPE_ENUM) {
StringBuilder value = new StringBuilder();
Modified:
openjpa/branches/2.2.x/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/meta/ClassMapping.java
URL:
http://svn.apache.org/viewvc/openjpa/branches/2.2.x/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/meta/ClassMapping.java?rev=1750037&r1=1750036&r2=1750037&view=diff
==============================================================================
---
openjpa/branches/2.2.x/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/meta/ClassMapping.java
(original)
+++
openjpa/branches/2.2.x/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/meta/ClassMapping.java
Fri Jun 24 03:31:13 2016
@@ -253,6 +253,32 @@ public class ClassMapping
sm = (OpenJPAStateManager) pc.pcGetStateManager();
if (sm == null) {
ret = getValueFromUnmanagedInstance(obj, cols, true);
+
+ // OPENJPA-2631 start
+ // Check to see if we are dealing with a Embeddable pk. If the
PK is an Embeddable, AND IFF the
+ // columns in the Embeddable are greater than 1, we are
dealing with a composite primary
+ // key, and as such 'ret' will be an instance of the
embeddable, NOT the individual PK values.
+ // Given this, we need to dig deeper and get the individual
values of the embeddable key.
+ // On the other hand, if the embeddable only contains one
column, 'ret' will be the value of
+ // that column and as such no further digging is necessary.
+ FieldMapping[] fmsPK = this.getPrimaryKeyFieldMappings();
+ List<FieldMapping> fms = getFieldMappings(cols, true);
+
+ // Note that if we are dealing with an embeddable that is an
EmbeddableId, the fms.size will
+ // always be 1 (since an EmbeddableId is slightly opaque, we
don't have an fms for each field).
+ // If on the other hand we are dealing with an embeddable that
is an @IdClass, fms.size will be the
+ // number columns in the @IdClass. Furthermore, when dealing
with @IdClass, 'ret' will already
+ // properly contain the column values, therefore no further
processing is needed.
+ if (fmsPK[0].isEmbedded() && cols.length > 1 && fms.size() ==
1) {
+ // OK, we know this PK is an embeddable. So get the
individual field values.
+ Object[] tmpRet = new Object[cols.length];
+ for (int i = 0; i < cols.length; i++) {
+ Joinable join = this.assertJoinable(cols[i]);
+ tmpRet[i] = join.getJoinValue(ret, cols[i], store);
+ }
+ ret = tmpRet;
+ }
+ // OPENJPA-2631 end
} else if (sm.isDetached()) {
obj = store.getContext().find(sm.getObjectId(), false, null);
sm = store.getContext().getStateManager(obj);