You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@openjpa.apache.org by ht...@apache.org on 2016/06/24 03:43:49 UTC

svn commit: r1750039 - in /openjpa/branches/2.2.1.x: ./ openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/exps/ openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/meta/ openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/embed...

Author: hthomann
Date: Fri Jun 24 03:43:49 2016
New Revision: 1750039

URL: http://svn.apache.org/viewvc?rev=1750039&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.1

Added:
    openjpa/branches/2.2.1.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.1.x/   (props changed)
    openjpa/branches/2.2.1.x/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/exps/EqualExpression.java
    openjpa/branches/2.2.1.x/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/exps/Lit.java
    openjpa/branches/2.2.1.x/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/meta/ClassMapping.java

Propchange: openjpa/branches/2.2.1.x/
------------------------------------------------------------------------------
--- svn:mergeinfo (original)
+++ svn:mergeinfo Fri Jun 24 03:43:49 2016
@@ -1,5 +1,5 @@
 /openjpa/branches/1.0.x:736493
 /openjpa/branches/2.0.x:1419659,1484136,1484287,1504611
-/openjpa/branches/2.1.x:1415379,1415398,1436150,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,1436150,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.x:1580898,1580939,1591681,1641906,1642555,1702143
 /openjpa/trunk:1416742,1420324,1430117,1431649,1436957,1436960,1448662,1448796,1451369,1456574,1456614,1459091,1461833,1469646,1469649,1469652,1504282,1564989,1600757,1603251

Modified: openjpa/branches/2.2.1.x/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/exps/EqualExpression.java
URL: http://svn.apache.org/viewvc/openjpa/branches/2.2.1.x/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/exps/EqualExpression.java?rev=1750039&r1=1750038&r2=1750039&view=diff
==============================================================================
--- openjpa/branches/2.2.1.x/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/exps/EqualExpression.java (original)
+++ openjpa/branches/2.2.1.x/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/exps/EqualExpression.java Fri Jun 24 03:43:49 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.1.x/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/exps/Lit.java
URL: http://svn.apache.org/viewvc/openjpa/branches/2.2.1.x/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/exps/Lit.java?rev=1750039&r1=1750038&r2=1750039&view=diff
==============================================================================
--- openjpa/branches/2.2.1.x/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/exps/Lit.java (original)
+++ openjpa/branches/2.2.1.x/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/exps/Lit.java Fri Jun 24 03:43:49 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.1.x/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/meta/ClassMapping.java
URL: http://svn.apache.org/viewvc/openjpa/branches/2.2.1.x/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/meta/ClassMapping.java?rev=1750039&r1=1750038&r2=1750039&view=diff
==============================================================================
--- openjpa/branches/2.2.1.x/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/meta/ClassMapping.java (original)
+++ openjpa/branches/2.2.1.x/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/meta/ClassMapping.java Fri Jun 24 03:43:49 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);