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 7db84f16f..4867bb898 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 @@ -32,6 +32,7 @@ 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.ValueMapping; +import org.apache.openjpa.jdbc.meta.strats.HandlerCollectionTableFieldStrategy; import org.apache.openjpa.jdbc.meta.strats.HandlerRelationMapTableFieldStrategy; import org.apache.openjpa.jdbc.schema.Column; import org.apache.openjpa.jdbc.schema.ForeignKey; @@ -253,8 +254,12 @@ public class PCPath return null; } else if (_keyPath) return pstate.field.getDefiningMapping(); - if (pstate.field.getElement().getTypeCode() == JavaTypes.PC) + if (pstate.field.getElement().getTypeCode() == JavaTypes.PC) { + if (pstate.field.isElementCollection() && + pstate.field.getElement().isEmbedded()) + pstate.isEmbedElementColl = true; return pstate.field.getElementMapping().getTypeMapping(); + } if (pstate.field.getTypeCode() == JavaTypes.PC) return pstate.field.getTypeMapping(); return null; @@ -291,8 +296,14 @@ public class PCPath case JavaTypes.ARRAY: case JavaTypes.COLLECTION: ValueMapping elem = pstate.field.getElementMapping(); - if (pstate.joinedRel && elem.getTypeCode() == JavaTypes.PC) + if (pstate.joinedRel && elem.getTypeCode() == JavaTypes.PC) { + if (pstate.field.isElementCollection() && + pstate.field.getElement().isEmbedded()) + return ((HandlerCollectionTableFieldStrategy) + pstate.field.getStrategy()).getElementColumns( + elem.getTypeMapping()); return elem.getTypeMapping().getPrimaryKeyColumns(); + } if (elem.getColumns().length > 0) return elem.getColumns(); return pstate.field.getColumns(); @@ -642,6 +653,7 @@ public class PCPath public FieldMapping cmpfield = null; public Column[] cols = null; public boolean joinedRel = false; + public boolean isEmbedElementColl = false; public PathExpState(Joins joins) { super(joins); @@ -722,7 +734,8 @@ public class PCPath boolean pks) { ClassMapping mapping = getClassMapping(state); PathExpState pstate = (PathExpState) state; - if (mapping == null || !pstate.joinedRel || _keyPath) + if (mapping == null || !pstate.joinedRel || _keyPath || + pstate.isEmbedElementColl) sel.select(getColumns(state), pstate.joins); else if (pks) sel.select(mapping.getPrimaryKeyColumns(), pstate.joins); @@ -784,7 +797,9 @@ public class PCPath else if (pstate.field.getKey().isEmbedded()) return loadEmbeddedMapKey(ctx, state, res); } - + if (pstate.isEmbedElementColl) + return pstate.field.loadProjection(ctx.store, ctx.fetch, res, + pstate.joins); return res.load(mapping, ctx.store, ctx.fetch, pstate.joins); } @@ -808,6 +823,8 @@ public class PCPath // 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)) diff --git a/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/meta/strats/ElementEmbedValueHandler.java b/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/meta/strats/ElementEmbedValueHandler.java index 0559d61e6..2250b87bf 100644 --- a/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/meta/strats/ElementEmbedValueHandler.java +++ b/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/meta/strats/ElementEmbedValueHandler.java @@ -110,10 +110,6 @@ public class ElementEmbedValueHandler public Object toObjectValue(ValueMapping vm, Object val, OpenJPAStateManager sm, JDBCStore store, JDBCFetchConfiguration fetch) throws SQLException { - if (sm == null) - throw new InvalidStateException(_loc.get("cant-project-owned", - vm)); - // check null indicator first if (_nullIdx != -1) { Object nval; diff --git a/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/StateManagerImpl.java b/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/StateManagerImpl.java index 5b5c8e0cf..f7a77ccdc 100644 --- a/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/StateManagerImpl.java +++ b/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/StateManagerImpl.java @@ -427,7 +427,8 @@ public class StateManagerImpl } public boolean isEmbedded() { - return _owner != null; + // _owner may not be set if embed object is from query result + return _owner != null || _state instanceof ENonTransState; } public boolean isFlushed() { diff --git a/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/embed/TestEmbeddable.java b/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/embed/TestEmbeddable.java index e4b57bc69..8b541ead4 100644 --- a/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/embed/TestEmbeddable.java +++ b/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/embed/TestEmbeddable.java @@ -1084,6 +1084,27 @@ public class TestEmbeddable extends SingleEMFTestCase { */ public void queryEntityA_Embed_Coll_Embed() { EntityManager em = emf.createEntityManager(); + // test select embed object from element collection + String[] query = { + "select e, e.intVal1, e.embed.intVal2 from " + + " EntityA_Coll_Embed_Embed a " + + " , in (a.embeds) e order by e.intVal3", + "select e, a.id from EntityA_Coll_Embed_Embed a " + + " , in (a.embeds) e order by a.id", + "select e, e.intVal1, e.embed.intVal2 from " + + " EntityA_Coll_Embed_Embed a " + + " , in (a.embeds) e order by e.intVal3", + }; + List rs = null; + for (int i = 0; i < query.length; i++) { + rs = em.createQuery(query[i]).getResultList(); + if (rs.size() > 0) { + Object obj = ((Object[]) rs.get(0))[0]; + assertTrue(obj instanceof Embed_Embed); + } + } + + em.clear(); EntityTransaction tran = em.getTransaction(); tran.begin(); Query q = em.createQuery("select a from EntityA_Embed_Coll_Embed a");