OPENJPA-967 JPA2 Query embeddable MapKey rework

git-svn-id: https://svn.apache.org/repos/asf/openjpa/trunk@761851 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
Catalina Wei 2009-04-04 01:10:30 +00:00
parent b6f8f0f4ec
commit 5e820a36c9
4 changed files with 69 additions and 38 deletions

View File

@ -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<Integer, Employee> 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<Integer, Employee> 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,

View File

@ -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();
}

View File

@ -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);

View File

@ -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);