From 5e820a36c9910d9240ea24a89bac5ace670eeaf1 Mon Sep 17 00:00:00 2001 From: Catalina Wei Date: Sat, 4 Apr 2009 01:10:30 +0000 Subject: [PATCH] OPENJPA-967 JPA2 Query embeddable MapKey rework git-svn-id: https://svn.apache.org/repos/asf/openjpa/trunk@761851 13f79535-47bb-0310-9956-ffa450edef68 --- .../openjpa/jdbc/kernel/exps/PCPath.java | 92 +++++++++++-------- .../maps/m2mmapex5/TestMany2ManyMapEx5.java | 8 ++ .../spec_10_1_26_ex1/TestSpec10_1_26_Ex1.java | 5 + .../spec_10_1_26_ex3/TestSpec10_1_26_Ex3.java | 2 +- 4 files changed, 69 insertions(+), 38 deletions(-) diff --git a/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/exps/PCPath.java b/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/exps/PCPath.java index 6b5ac4571..5fa72d49b 100644 --- a/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/exps/PCPath.java +++ b/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/exps/PCPath.java @@ -25,15 +25,15 @@ import java.util.LinkedList; import java.util.ListIterator; import org.apache.commons.lang.ObjectUtils; -import org.apache.openjpa.enhance.PersistenceCapable; import org.apache.openjpa.jdbc.kernel.JDBCFetchConfiguration; import org.apache.openjpa.jdbc.meta.ClassMapping; import org.apache.openjpa.jdbc.meta.Discriminator; import org.apache.openjpa.jdbc.meta.FieldMapping; -import org.apache.openjpa.jdbc.meta.JavaSQLTypes; +import org.apache.openjpa.jdbc.meta.Strategy; import org.apache.openjpa.jdbc.meta.ValueMapping; import org.apache.openjpa.jdbc.meta.strats.HandlerCollectionTableFieldStrategy; import org.apache.openjpa.jdbc.meta.strats.HandlerRelationMapTableFieldStrategy; +import org.apache.openjpa.jdbc.meta.strats.LRSMapFieldStrategy; import org.apache.openjpa.jdbc.schema.Column; import org.apache.openjpa.jdbc.schema.ForeignKey; import org.apache.openjpa.jdbc.schema.Schemas; @@ -44,7 +44,6 @@ import org.apache.openjpa.jdbc.sql.Select; import org.apache.openjpa.kernel.Broker; import org.apache.openjpa.kernel.Filters; import org.apache.openjpa.kernel.OpenJPAStateManager; -import org.apache.openjpa.kernel.StateManagerImpl; import org.apache.openjpa.kernel.StoreContext; import org.apache.openjpa.kernel.exps.CandidatePath; import org.apache.openjpa.lib.util.Localizer; @@ -247,8 +246,6 @@ public class PCPath if (pstate.field == null) return _class; if (_key) { - if (pstate.field.getKey().getValueMappedBy() != null) - return _class; if (pstate.field.getKey().getTypeCode() == JavaTypes.PC) return pstate.field.getKeyMapping().getTypeMapping(); return null; @@ -381,6 +378,7 @@ public class PCPath action.op = Action.GET_KEY; _cast = null; _key = true; + _type = PATH; } public FieldMetaData last() { @@ -493,8 +491,11 @@ public class PCPath forceOuter |= action.op == Action.GET_OUTER; // if last action is get map key, use the previous field mapping - if (key && !itr.hasNext()) + if (key && !itr.hasNext()) { field = pstate.field; + pstate.joins = pstate.joins.setVariable((String) + action.data); + } if (pstate.field != null) { // if this is the second-to-last field and the last is @@ -739,6 +740,8 @@ public class PCPath if (mapping == null || !pstate.joinedRel || _keyPath || pstate.isEmbedElementColl) sel.select(getColumns(state), pstate.joins); + else if (_key && pstate.field.getKey().isEmbedded()) + selectEmbeddedMapKey(sel, ctx, state); else if (pks) sel.select(mapping.getPrimaryKeyColumns(), pstate.joins); else { @@ -786,19 +789,8 @@ public class PCPath if (pks) return mapping.getObjectId(ctx.store, res, null, true, pstate.joins); - if (_key) { - if (pstate.field.getKey().getValueMappedBy() != null) { - Object obj = res.load(mapping, ctx.store, ctx.fetch, - pstate.joins); - StateManagerImpl sm = (StateManagerImpl) - ((PersistenceCapable) obj).pcGetStateManager(); - obj = sm.fetch(_class.getField(pstate.field.getKey(). - getValueMappedBy()).getIndex()); - return obj; - } - else if (pstate.field.getKey().isEmbedded()) - return loadEmbeddedMapKey(ctx, state, res); - } + if (_key && pstate.field.getKey().isEmbedded()) + return loadEmbeddedMapKey(ctx, state, res); if (pstate.isEmbedElementColl) return pstate.field.loadProjection(ctx.store, ctx.fetch, res, pstate.joins); @@ -807,10 +799,15 @@ public class PCPath Object ret; if (_key) - // Map key is a java primitive type - // example: Map emps - ret = res.getObject(pstate.cols[0], - JavaSQLTypes.JDBC_DEFAULT, pstate.joins); + if (pstate.field.getKey().getValueMappedBy() != null) + ret = ((FieldMapping) pstate.field.getKey(). + getValueMappedByMetaData()). + loadProjection(ctx.store, ctx.fetch, res, pstate.joins); + else + // Map key is a java primitive type + // example: Map emps + ret = res.getObject(pstate.cols[0], + null, pstate.joins); else ret = pstate.field.loadProjection(ctx.store, ctx.fetch, res, pstate.joins); @@ -819,23 +816,44 @@ public class PCPath return ret; } + private void validateMapStrategy(Strategy strategy) { + if (strategy == null || + !(strategy instanceof LRSMapFieldStrategy)) + throw new RuntimeException("Invalid map field strategy:"+strategy); + } + + private void selectEmbeddedMapKey(Select sel, ExpContext ctx, + ExpState state) { + PathExpState pstate = (PathExpState) state; + validateMapStrategy(pstate.field.getStrategy()); + LRSMapFieldStrategy strategy = (LRSMapFieldStrategy) + pstate.field.getStrategy(); + ClassMapping mapping = pstate.field.getKeyMapping().getTypeMapping(); + if (strategy instanceof HandlerRelationMapTableFieldStrategy) + strategy.selectKey(sel, mapping, null, ctx.store, ctx.fetch, + pstate.joins); + else { + sel.select(_class.getPrimaryKeyColumns(), pstate.joins); + FieldMapping[] fms = mapping.getDefinedFieldMappings(); + for (int i = 0; i < fms.length; i++) + sel.select(fms[i].getColumns(), pstate.joins); + } + } + private Object loadEmbeddedMapKey(ExpContext ctx, ExpState state, Result res) throws SQLException { PathExpState pstate = (PathExpState) state; - // consume keyProjection - PersistenceCapable pc = (PersistenceCapable) res.load(_candidate, - ctx.store, ctx.fetch, pstate.joins); - if (pc == null) - return null; - if (pstate.field.getStrategy() == null || - !(pstate.field.getStrategy() instanceof - HandlerRelationMapTableFieldStrategy)) - throw new RuntimeException("Invalid map field strategy"); - HandlerRelationMapTableFieldStrategy strategy = - (HandlerRelationMapTableFieldStrategy) pstate.field.getStrategy(); - return strategy - .loadKey((OpenJPAStateManager) pc.pcGetStateManager(), - ctx.store, ctx.fetch, res, pstate.joins); + validateMapStrategy(pstate.field.getStrategy()); + FieldMapping fmd = (FieldMapping) pstate.field.getKey(). + getValueMappedByMetaData(); + LRSMapFieldStrategy strategy = + (LRSMapFieldStrategy) pstate.field.getStrategy(); + if (strategy instanceof HandlerRelationMapTableFieldStrategy) + return strategy.loadKey(null, ctx.store, ctx.fetch, res, + pstate.joins); + else + return fmd.getStrategy(). + loadProjection(ctx.store, ctx.fetch, res, pstate.joins); } public void calculateValue(Select sel, ExpContext ctx, ExpState state, diff --git a/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/jdbc/maps/m2mmapex5/TestMany2ManyMapEx5.java b/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/jdbc/maps/m2mmapex5/TestMany2ManyMapEx5.java index fbf57bf9f..f8f50d0d2 100644 --- a/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/jdbc/maps/m2mmapex5/TestMany2ManyMapEx5.java +++ b/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/jdbc/maps/m2mmapex5/TestMany2ManyMapEx5.java @@ -115,6 +115,14 @@ public class TestMany2ManyMapEx5 extends SQLListenerTestCase { assertTrue(d.equals(me.getKey())); + query = "select p from PhoneNumber p," + + " in (p.emps) e where Key(e) = 'String2' order by p.number"; + q = em.createQuery(query); + if (inMemory) + setCandidate(q, PhoneNumber.class); + rs = q.getResultList(); + assertEquals(((PhoneNumber) rs.get(0)).getNumber(), 3); + em.close(); } diff --git a/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/jdbc/maps/spec_10_1_26_ex1/TestSpec10_1_26_Ex1.java b/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/jdbc/maps/spec_10_1_26_ex1/TestSpec10_1_26_Ex1.java index 29afa41b1..b3562bf56 100644 --- a/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/jdbc/maps/spec_10_1_26_ex1/TestSpec10_1_26_Ex1.java +++ b/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/jdbc/maps/spec_10_1_26_ex1/TestSpec10_1_26_Ex1.java @@ -73,6 +73,11 @@ public class TestSpec10_1_26_Ex1 extends SQLListenerTestCase { public void queryQualifiedId(boolean inMemory) throws Exception { EntityManager em = emf.createEntityManager(); + String query1 = "select d.deptId, KEY(e), VALUE(e).empId " + + "from Department d, in (d.empMap) e"; +List rs1 = em.createQuery(query1).getResultList(); +System.out.println("rs size="+rs1.size()); + String query = "select KEY(e) from Department d, " + " in (d.empMap) e order by d.deptId, e.empId"; Query q = em.createQuery(query); diff --git a/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/jdbc/maps/spec_10_1_26_ex3/TestSpec10_1_26_Ex3.java b/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/jdbc/maps/spec_10_1_26_ex3/TestSpec10_1_26_Ex3.java index 4bb2e213a..63e4adb11 100644 --- a/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/jdbc/maps/spec_10_1_26_ex3/TestSpec10_1_26_Ex3.java +++ b/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/jdbc/maps/spec_10_1_26_ex3/TestSpec10_1_26_Ex3.java @@ -95,7 +95,7 @@ public class TestSpec10_1_26_Ex3 extends SQLListenerTestCase { // test ORDER BY qualified path query = "select KEY(e), KEY(e).fName from Department d, " + - " in (d.emps) e order by KEY(e).fName"; + " in (d.emps) e order by d.deptId"; q = em.createQuery(query); if (inMemory) setCandidate(q, Department.class);