Author: ppoddar
Date: Wed Nov 17 00:38:17 2010
New Revision: 1035884
URL: http://svn.apache.org/viewvc?rev=1035884&view=rev
Log:
OPENJPA-1889: Relax binding query parameter type checks for enums
Modified:
openjpa/trunk/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/Filters.java
openjpa/trunk/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/QueryHints.java
openjpa/trunk/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/HintHandler.java
openjpa/trunk/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/OpenJPAQuery.java
openjpa/trunk/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/QueryImpl.java
Modified:
openjpa/trunk/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/Filters.java
URL:
http://svn.apache.org/viewvc/openjpa/trunk/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/Filters.java?rev=1035884&r1=1035883&r2=1035884&view=diff
==============================================================================
---
openjpa/trunk/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/Filters.java
(original)
+++
openjpa/trunk/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/Filters.java
Wed Nov 17 00:38:17 2010
@@ -328,6 +328,8 @@ public class Filters {
} catch (IllegalArgumentException e) {
}
+ } else if (o instanceof String && type.isEnum()) {
+ return Enum.valueOf((Class<Enum>)type, o.toString());
}
}
if (!num)
Modified:
openjpa/trunk/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/QueryHints.java
URL:
http://svn.apache.org/viewvc/openjpa/trunk/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/QueryHints.java?rev=1035884&r1=1035883&r2=1035884&view=diff
==============================================================================
---
openjpa/trunk/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/QueryHints.java
(original)
+++
openjpa/trunk/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/QueryHints.java
Wed Nov 17 00:38:17 2010
@@ -43,8 +43,7 @@ public interface QueryHints {
* to count number of parameters assuming that all <code>?</code>
characters
* designate a bind parameter. This assumption makes the parse faster.
*/
- public static final String HINT_PARAM_MARKER_IN_QUERY =
- "openjpa.hint.ParameterMarkerInQuery";
+ public static final String HINT_PARAM_MARKER_IN_QUERY =
"openjpa.hint.ParameterMarkerInQuery";
/**
* A directive to invalidate any prepared SQL that might have been cached
@@ -61,8 +60,7 @@ public interface QueryHints {
*
* @see #HINT_IGNORE_PREPARED_QUERY
*/
- public static final String HINT_INVALIDATE_PREPARED_QUERY =
- "openjpa.hint.InvalidatePreparedQuery";
+ public static final String HINT_INVALIDATE_PREPARED_QUERY =
"openjpa.hint.InvalidatePreparedQuery";
/**
* A directive to ignore any prepared SQL that might have been cached
@@ -80,8 +78,7 @@ public interface QueryHints {
*
* @see #HINT_INVALIDATE_PREPARED_QUERY
*/
- public static final String HINT_IGNORE_PREPARED_QUERY =
- "openjpa.hint.IgnorePreparedQuery";
+ public static final String HINT_IGNORE_PREPARED_QUERY =
"openjpa.hint.IgnorePreparedQuery";
/**
* A directive to ignore any cached finder query for find() operation.
@@ -92,12 +89,17 @@ public interface QueryHints {
/**
* A directive to invalidate any cached finder query.
*/
- public static final String HINT_INVALIDATE_FINDER =
- "openjpa.hint.InvalidateFinder";
+ public static final String HINT_INVALIDATE_FINDER =
"openjpa.hint.InvalidateFinder";
/**
* A directive to overwrite a cached finder query by a new query.
*/
public static final String HINT_RECACHE_FINDER =
"openjpa.hint.RecacheFinder";
+
+ /**
+ * A boolean directive to relax checking of binding parameter value and
the predicate
+ * it binds to.
+ */
+ public static final String HINT_RELAX_BIND_PARAM_TYPE_CHECK =
"openjpa.hint.RelaxParameterTypeChecking";
}
Modified:
openjpa/trunk/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/HintHandler.java
URL:
http://svn.apache.org/viewvc/openjpa/trunk/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/HintHandler.java?rev=1035884&r1=1035883&r2=1035884&view=diff
==============================================================================
---
openjpa/trunk/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/HintHandler.java
(original)
+++
openjpa/trunk/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/HintHandler.java
Wed Nov 17 00:38:17 2010
@@ -150,6 +150,8 @@ public class HintHandler {
if (value instanceof String)
value = Boolean.valueOf((String) value);
owner.setSubclasses(((Boolean) value).booleanValue());
+ } else if (QueryHints.HINT_RELAX_BIND_PARAM_TYPE_CHECK.equals(key)) {
+ owner.setRelaxBindParameterTypeChecking(value);
} else if (QueryHints.HINT_FILTER_LISTENER.equals(key)) {
owner.addFilterListener(Filters.hintToFilterListener(value,
loader));
} else if (QueryHints.HINT_FILTER_LISTENERS.equals(key)) {
Modified:
openjpa/trunk/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/OpenJPAQuery.java
URL:
http://svn.apache.org/viewvc/openjpa/trunk/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/OpenJPAQuery.java?rev=1035884&r1=1035883&r2=1035884&view=diff
==============================================================================
---
openjpa/trunk/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/OpenJPAQuery.java
(original)
+++
openjpa/trunk/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/OpenJPAQuery.java
Wed Nov 17 00:38:17 2010
@@ -25,9 +25,11 @@ import java.util.Map;
import java.util.Set;
import javax.persistence.FlushModeType;
+import javax.persistence.Query;
import javax.persistence.TemporalType;
import javax.persistence.TypedQuery;
+import org.apache.openjpa.kernel.Filters;
import org.apache.openjpa.kernel.QueryFlushModes;
import org.apache.openjpa.kernel.QueryHints;
import org.apache.openjpa.kernel.QueryOperations;
@@ -177,19 +179,39 @@ public interface OpenJPAQuery<X> extends
public OpenJPAQuery<X> setParameter(String name, Object value);
- public OpenJPAQuery<X> setParameter(String name, Date value,
- TemporalType temporalType);
+ public OpenJPAQuery<X> setParameter(String name, Date value, TemporalType
temporalType);
- public OpenJPAQuery<X> setParameter(String name, Calendar value,
- TemporalType temporalType);
+ public OpenJPAQuery<X> setParameter(String name, Calendar value,
TemporalType temporalType);
public OpenJPAQuery<X> setParameter(int position, Object value);
- public OpenJPAQuery<X> setParameter(int position, Date value,
- TemporalType temporalType);
+ public OpenJPAQuery<X> setParameter(int position, Date value, TemporalType
temporalType);
- public OpenJPAQuery<X> setParameter(int position, Calendar value,
- TemporalType temporalType);
+ public OpenJPAQuery<X> setParameter(int position, Calendar value,
TemporalType temporalType);
+
+ /**
+ * Sets whether the type of user-supplied bind parameter value and the
type of target persistent
+ * property they bind to are checked with strong or weak constraint.
+ * <br>
+ * The same can be set via {...@link Query#setHint(String, Object) hint}
without puncturing standard
+ * JPA API.
+ *
+ * @see Filters#canConvert(Class, Class, boolean)
+ * @see Filters#convert(Object, Class, boolean)
+ *
+ * @param hint a String or Boolean value.
+ */
+ public void setRelaxBindParameterTypeChecking(Object hint);
+
+ /**
+ * Gets whether the type of user-supplied bind parameter value and the
type of target persistent
+ * property they bind to are checked with strong or weak constraint.
+ *
+ * @return the booelan state. False by default, i.e. the type of a bind
parameter value is checked
+ * strongly against the target property type.
+ */
+ public boolean getRelaxBindParameterTypeChecking();
+
public OpenJPAQuery<X> setFlushMode(FlushModeType flushMode);
@@ -233,29 +255,25 @@ public interface OpenJPAQuery<X> extends
* @deprecated cast to {...@link QueryImpl} instead. This
* method pierces the published-API boundary, as does the SPI cast.
*/
- public OpenJPAQuery<X> addFilterListener(
- org.apache.openjpa.kernel.exps.FilterListener listener);
+ public OpenJPAQuery<X>
addFilterListener(org.apache.openjpa.kernel.exps.FilterListener listener);
/**
* @deprecated cast to {...@link QueryImpl} instead. This
* method pierces the published-API boundary, as does the SPI cast.
*/
- public OpenJPAQuery<X> removeFilterListener(
- org.apache.openjpa.kernel.exps.FilterListener listener);
+ public OpenJPAQuery<X>
removeFilterListener(org.apache.openjpa.kernel.exps.FilterListener listener);
/**
* @deprecated cast to {...@link QueryImpl} instead. This
* method pierces the published-API boundary, as does the SPI cast.
*/
- public OpenJPAQuery<X> addAggregateListener(
- org.apache.openjpa.kernel.exps.AggregateListener listener);
+ public OpenJPAQuery<X>
addAggregateListener(org.apache.openjpa.kernel.exps.AggregateListener listener);
/**
* @deprecated cast to {...@link QueryImpl} instead. This
* method pierces the published-API boundary, as does the SPI cast.
*/
- public OpenJPAQuery<X> removeAggregateListener(
- org.apache.openjpa.kernel.exps.AggregateListener listener);
+ public OpenJPAQuery<X>
removeAggregateListener(org.apache.openjpa.kernel.exps.AggregateListener
listener);
/**
* Gets hints supported by this query.
Modified:
openjpa/trunk/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/QueryImpl.java
URL:
http://svn.apache.org/viewvc/openjpa/trunk/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/QueryImpl.java?rev=1035884&r1=1035883&r2=1035884&view=diff
==============================================================================
---
openjpa/trunk/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/QueryImpl.java
(original)
+++
openjpa/trunk/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/QueryImpl.java
Wed Nov 17 00:38:17 2010
@@ -54,6 +54,7 @@ import org.apache.openjpa.kernel.FetchCo
import org.apache.openjpa.kernel.Filters;
import org.apache.openjpa.kernel.PreparedQuery;
import org.apache.openjpa.kernel.PreparedQueryCache;
+import org.apache.openjpa.kernel.QueryHints;
import org.apache.openjpa.kernel.QueryLanguages;
import org.apache.openjpa.kernel.QueryOperations;
import org.apache.openjpa.kernel.QueryStatistics;
@@ -91,7 +92,8 @@ public class QueryImpl<X> implements Ope
private String _id;
private transient ReentrantLock _lock = null;
private HintHandler _hintHandler;
-
+ private boolean _relaxBindParameterTypeChecking;
+
/**
* Constructor; supply factory exception translator and delegate.
*
@@ -253,6 +255,20 @@ public class QueryImpl<X> implements Ope
_query.setRange(start, start + max);
return this;
}
+
+ public boolean getRelaxBindParameterTypeChecking() {
+ return _relaxBindParameterTypeChecking;
+ }
+
+ public void setRelaxBindParameterTypeChecking(Object value) {
+ if (value != null) {
+ if (value instanceof String) {
+ _relaxBindParameterTypeChecking =
"true".equalsIgnoreCase(value.toString());
+ } else if (value instanceof Boolean) {
+ _relaxBindParameterTypeChecking =
((Boolean)value).booleanValue();
+ }
+ }
+ }
public OpenJPAQuery<X> compile() {
_em.assertNotCloseInvoked();
@@ -323,7 +339,7 @@ public class QueryImpl<X> implements Ope
*/
public X getSingleResult() {
_em.assertNotCloseInvoked();
- setHint("openjpa.hint.OptimizeResultCount", 1); // for DB2 optimization
+ setHint(QueryHints.HINT_RESULT_COUNT, 1); // for DB2 optimization
List result = getResultList();
if (result == null || result.isEmpty())
throw new NoResultException(_loc.get("no-result", getQueryString())
@@ -1042,10 +1058,10 @@ public class QueryImpl<X> implements Ope
* Validates if the parameter can accept the value by its type.
*/
void bindValue(Parameter<?> param, Object value) {
- assertValueAssignable(param, value);
+ Object bindVal = assertValueAssignable(param, value);
if (_boundParams == null)
_boundParams = new HashMap<Parameter<?>, Object>();
- _boundParams.put(param, value);
+ _boundParams.put(param, bindVal);
}
public OpenJPAQuery<X> setParameter(String name, Calendar value,
TemporalType type) {
@@ -1078,15 +1094,33 @@ public class QueryImpl<X> implements Ope
}
}
- void assertValueAssignable(Parameter<?> param, Object v) {
+ /**
+ * Convert the given value to match the given parameter type, if possible.
+ *
+ * @param param a query parameter
+ * @param v a user-supplied value for the parameter
+ */
+ Object assertValueAssignable(Parameter<?> param, Object v) {
+ Class<?> expectedType = param.getParameterType();
if (v == null) {
- if (param.getParameterType().isPrimitive())
+ if (expectedType.isPrimitive())
throw new
IllegalArgumentException(_loc.get("param-null-primitive", param).getMessage());
- return;
+ return v;
}
- if (!Filters.canConvert(v.getClass(), param.getParameterType(), true))
{
- throw new IllegalArgumentException(_loc.get("param-type-mismatch",
new Object[]{
- param, getQueryString(), v, v.getClass().getName(),
param.getParameterType().getName()}).getMessage());
+ if (getRelaxBindParameterTypeChecking()) {
+ try {
+ return Filters.convert(v, expectedType);
+ } catch (Exception e) {
+ throw new
IllegalArgumentException(_loc.get("param-type-mismatch", new Object[]{
+ param, getQueryString(), v, v.getClass().getName(),
expectedType.getName()}).getMessage());
+ }
+ } else {
+ if (!Filters.canConvert(v.getClass(), expectedType, true)) {
+ throw new
IllegalArgumentException(_loc.get("param-type-mismatch", new Object[]{
+ param, getQueryString(), v, v.getClass().getName(),
expectedType.getName()}).getMessage());
+ } else {
+ return v;
+ }
}
}