mirror of https://github.com/apache/openjpa.git
OPENJPA-1013: Add support for JPA 2.0 result processing. Modify kerenl's ResultPacking logic to asses impact for JPA 2.0"
git-svn-id: https://svn.apache.org/repos/asf/openjpa/trunk@799466 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
parent
3ae614fc26
commit
39cad98231
|
@ -18,6 +18,7 @@
|
|||
*/
|
||||
package org.apache.openjpa.kernel;
|
||||
|
||||
import java.lang.reflect.Array;
|
||||
import java.lang.reflect.Constructor;
|
||||
import java.lang.reflect.Field;
|
||||
import java.lang.reflect.Member;
|
||||
|
@ -108,7 +109,12 @@ public class ResultPacker {
|
|||
private ResultPacker(Class candidate, Class[] types, String[] aliases,
|
||||
Class resultClass) {
|
||||
_aliases = aliases;
|
||||
if (resultClass.isPrimitive()) {
|
||||
if (candidate == resultClass || resultClass.isArray()) {
|
||||
_resultClass = resultClass;
|
||||
_sets = null;
|
||||
_put = null;
|
||||
_constructor = null;
|
||||
} else if (resultClass.isPrimitive()) {
|
||||
assertConvertable(candidate, types, resultClass);
|
||||
_resultClass = Filters.wrap(resultClass);
|
||||
_sets = null;
|
||||
|
@ -170,6 +176,8 @@ public class ResultPacker {
|
|||
* Pack the given object into an instance of the query's result class.
|
||||
*/
|
||||
public Object pack(Object result) {
|
||||
if (_resultClass == result.getClass())
|
||||
return result;
|
||||
// special cases for efficient basic types where we want to avoid
|
||||
// creating an array for call to general pack method below
|
||||
if (_resultClass == Object.class)
|
||||
|
@ -208,6 +216,13 @@ public class ResultPacker {
|
|||
}
|
||||
return result;
|
||||
}
|
||||
if (_resultClass.isArray()) {
|
||||
Class<?> elementType = _resultClass.getComponentType();
|
||||
Object castResult = Array.newInstance(elementType, result.length);
|
||||
for (int i = 0; i < result.length; i++)
|
||||
Array.set(castResult, i, elementType.cast(result[i]));
|
||||
return castResult;
|
||||
}
|
||||
if (_resultClass == Object.class)
|
||||
return result[0];
|
||||
if (_resultClass == HashMap.class || _resultClass == Map.class) {
|
||||
|
|
|
@ -30,6 +30,7 @@ import org.apache.openjpa.persistence.criteria.CriteriaTest;
|
|||
import org.apache.openjpa.persistence.criteria.Person;
|
||||
import org.apache.openjpa.persistence.criteria.Person_;
|
||||
import org.apache.openjpa.persistence.test.AllowFailure;
|
||||
import org.apache.openjpa.util.UserException;
|
||||
|
||||
|
||||
/**
|
||||
|
@ -39,7 +40,7 @@ import org.apache.openjpa.persistence.test.AllowFailure;
|
|||
*
|
||||
*/
|
||||
|
||||
@AllowFailure(value=true, message="Tests:16 Errors:1 Failure:7")
|
||||
@AllowFailure(value=false, message="Tests:16 Errors:1 Failure:1")
|
||||
public class TestMultiselect extends CriteriaTest {
|
||||
private static final Class[] CLASSES = {Person.class};
|
||||
private static boolean initialized = false;
|
||||
|
@ -148,6 +149,7 @@ public class TestMultiselect extends CriteriaTest {
|
|||
assertResult(q, String[].class);
|
||||
}
|
||||
|
||||
@AllowFailure(message="TupleArray needs special processing at multiselect")
|
||||
public void testTupleArray() {
|
||||
CriteriaQuery<Tuple[]> q = cb.createQuery(Tuple[].class);
|
||||
Root<Person> p = q.from(Person.class);
|
||||
|
@ -229,6 +231,8 @@ public class TestMultiselect extends CriteriaTest {
|
|||
assertResult(q, Object[].class, String.class, Integer.class);
|
||||
}
|
||||
|
||||
@AllowFailure(message="Mixing constructor with other projections get CriteriaExpressionBuilder.getProjections() " +
|
||||
"all messed up")
|
||||
public void testSingleObjectMultipleProjectionsAndConstructor() {
|
||||
CriteriaQuery<Object> q = cb.createQuery(Object.class);
|
||||
Root<Person> p = q.from(Person.class);
|
||||
|
@ -255,12 +259,13 @@ public class TestMultiselect extends CriteriaTest {
|
|||
List<?> result = em.createQuery(q).getResultList();
|
||||
assertFalse(result.isEmpty());
|
||||
for (Object row : result) {
|
||||
assertTrue(row.getClass() + " does not match actual result " + resultClass, resultClass.isInstance(row));
|
||||
assertTrue(toClass(row) + " does not match actual result " + toString(resultClass),
|
||||
resultClass.isInstance(row));
|
||||
if (resultClass.isArray() && arrayElementClasses != null) {
|
||||
for (int i = 0; i < arrayElementClasses.length; i++) {
|
||||
Object element = Array.get(row, i);
|
||||
assertTrue(i + "-th array element " + arrayElementClasses[i] + " does not match actual result "
|
||||
+ element.getClass(), arrayElementClasses[i].isInstance(element));
|
||||
assertTrue(i + "-th array element " + toString(arrayElementClasses[i]) +
|
||||
" does not match actual result " + toClass(element), arrayElementClasses[i].isInstance(element));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -270,8 +275,16 @@ public class TestMultiselect extends CriteriaTest {
|
|||
try {
|
||||
em.createQuery(q).getResultList();
|
||||
fail("Expected to fail " + msg);
|
||||
} catch (PersistenceException e) {
|
||||
} catch (UserException e) {
|
||||
// this is an expected exception
|
||||
}
|
||||
}
|
||||
|
||||
String toClass(Object o) {
|
||||
return toString(o.getClass());
|
||||
}
|
||||
|
||||
String toString(Class<?> cls) {
|
||||
return cls.isArray() ? toString(cls.getComponentType())+"[]" : cls.toString();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -71,7 +71,7 @@ public class CriteriaExpressionBuilder {
|
|||
|
||||
//exps.operation = QueryOperations.OP_SELECT;
|
||||
//exps.range = null; // Value[]
|
||||
//exps.resultClass = null; // Class
|
||||
exps.resultClass = q.getRuntimeResultClass();
|
||||
exps.parameterTypes = q.getParameterTypes();
|
||||
return exps;
|
||||
}
|
||||
|
@ -240,13 +240,10 @@ public class CriteriaExpressionBuilder {
|
|||
ExpressionFactory factory, CriteriaQueryImpl<?> q, MetamodelImpl model,
|
||||
Map<Expression<?>, Value> exp2Vals) {
|
||||
for (Selection<?> s : selections) {
|
||||
if(s instanceof TupleSelection<?> ) {
|
||||
exps.resultClass = TupleImpl.class;
|
||||
if (s instanceof TupleSelection<?> ) {
|
||||
getProjections(exps, ((TupleSelection<?>)s).getSelectionItems(), projections, aliases,
|
||||
clauses, factory, q, model, exp2Vals);
|
||||
}
|
||||
else if (s instanceof NewInstanceSelection<?>) {
|
||||
exps.resultClass = s.getJavaType();
|
||||
} else if (s instanceof NewInstanceSelection<?>) {
|
||||
getProjections(exps, ((NewInstanceSelection<?>)s).getSelectionItems(), projections, aliases,
|
||||
clauses, factory, q, model, exp2Vals);
|
||||
} else {
|
||||
|
|
|
@ -29,6 +29,7 @@ import java.util.Map;
|
|||
import java.util.Set;
|
||||
import java.util.Stack;
|
||||
|
||||
import javax.persistence.Tuple;
|
||||
import javax.persistence.criteria.AbstractQuery;
|
||||
import javax.persistence.criteria.CriteriaQuery;
|
||||
import javax.persistence.criteria.Expression;
|
||||
|
@ -46,6 +47,7 @@ import org.apache.openjpa.kernel.exps.Context;
|
|||
import org.apache.openjpa.kernel.exps.ExpressionFactory;
|
||||
import org.apache.openjpa.kernel.exps.QueryExpressions;
|
||||
import org.apache.openjpa.kernel.exps.Value;
|
||||
import org.apache.openjpa.persistence.TupleImpl;
|
||||
import org.apache.openjpa.persistence.meta.MetamodelImpl;
|
||||
import org.apache.openjpa.persistence.meta.Types;
|
||||
|
||||
|
@ -75,6 +77,7 @@ public class CriteriaQueryImpl<T> implements CriteriaQuery<T>, AliasContext {
|
|||
private Boolean _distinct;
|
||||
private SubqueryImpl<?> _delegator;
|
||||
private final Class<T> _resultClass;
|
||||
private Class<?> _runtimeResultClass;
|
||||
|
||||
// AliasContext
|
||||
private int aliasCount = 0;
|
||||
|
@ -95,6 +98,7 @@ public class CriteriaQueryImpl<T> implements CriteriaQuery<T>, AliasContext {
|
|||
public CriteriaQueryImpl(MetamodelImpl model, Class<T> resultClass) {
|
||||
this._model = model;
|
||||
this._resultClass = resultClass;
|
||||
_runtimeResultClass = Tuple.class.isAssignableFrom(resultClass) ? TupleImpl.class : resultClass;
|
||||
_aliases = new HashMap<Selection<?>, String>();
|
||||
}
|
||||
|
||||
|
@ -180,6 +184,8 @@ public class CriteriaQueryImpl<T> implements CriteriaQuery<T>, AliasContext {
|
|||
* @return the modified query
|
||||
*/
|
||||
public CriteriaQuery<T> multiselect(Selection<?>... selections) {
|
||||
if (selections.length > 1 && _resultClass == Object.class)
|
||||
_runtimeResultClass = Object[].class;
|
||||
return select(selections);
|
||||
}
|
||||
|
||||
|
@ -524,13 +530,15 @@ public class CriteriaQueryImpl<T> implements CriteriaQuery<T>, AliasContext {
|
|||
return ((SubqueryImpl<?>)parent).getDelegate().getRegisteredRootVariable(root);
|
||||
}
|
||||
|
||||
public Class getResultType() {
|
||||
// TODO Auto-generated method stub
|
||||
return null;
|
||||
public Class<T> getResultType() {
|
||||
return _resultClass;
|
||||
}
|
||||
|
||||
public Class<?> getRuntimeResultClass() {
|
||||
return _runtimeResultClass;
|
||||
}
|
||||
|
||||
public CriteriaQuery<T> multiselect(List<Selection<?>> arg0) {
|
||||
// TODO Auto-generated method stub
|
||||
return null;
|
||||
public CriteriaQuery<T> multiselect(List<Selection<?>> list) {
|
||||
return multiselect(list.toArray(new Selection<?>[list.size()]));
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue