You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@openjpa.apache.org by cu...@apache.org on 2011/11/17 20:13:08 UTC
svn commit: r1203337 - in /openjpa/trunk:
openjpa-kernel/src/main/java/org/apache/openjpa/meta/
openjpa-persistence/src/main/java/org/apache/openjpa/persistence/
Author: curtisr7
Date: Thu Nov 17 19:13:07 2011
New Revision: 1203337
URL: http://svn.apache.org/viewvc?rev=1203337&view=rev
Log:
OPENJPA-2075: Abstract parameter handling from QueryImpl.
Added:
openjpa/trunk/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/AbstractQuery.java
Modified:
openjpa/trunk/openjpa-kernel/src/main/java/org/apache/openjpa/meta/QueryMetaData.java
openjpa/trunk/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/EntityManagerImpl.java
openjpa/trunk/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/ParameterImpl.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/meta/QueryMetaData.java
URL: http://svn.apache.org/viewvc/openjpa/trunk/openjpa-kernel/src/main/java/org/apache/openjpa/meta/QueryMetaData.java?rev=1203337&r1=1203336&r2=1203337&view=diff
==============================================================================
--- openjpa/trunk/openjpa-kernel/src/main/java/org/apache/openjpa/meta/QueryMetaData.java (original)
+++ openjpa/trunk/openjpa-kernel/src/main/java/org/apache/openjpa/meta/QueryMetaData.java Thu Nov 17 19:13:07 2011
@@ -28,6 +28,7 @@ import org.apache.openjpa.kernel.Query;
import org.apache.openjpa.kernel.QueryLanguages;
import org.apache.openjpa.kernel.jpql.JPQLParser;
import org.apache.openjpa.lib.meta.SourceTracker;
+import org.apache.openjpa.lib.util.OrderedMap;
import org.apache.openjpa.lib.xml.Commentable;
/**
@@ -62,7 +63,8 @@ public class QueryMetaData
private int _colNum;
private String _srcName;
private boolean _convertPositionalParametersToNamed;
-
+ private OrderedMap<Object,Class<?>> _paramTypes;
+
/**
* Construct with the given name.
*/
@@ -306,4 +308,15 @@ public class QueryMetaData
public String getSourceName() {
return _srcName;
}
+
+ public void setParamTypes(OrderedMap<Object, Class<?>> paramTypes) {
+ _paramTypes = paramTypes;
+ }
+
+ /**
+ * @return a map of parameter name to type for this named query or <b>null if this data hasn't been set.</b>
+ */
+ public OrderedMap<Object, Class<?>> getParamTypes() {
+ return _paramTypes;
+ }
}
Added: openjpa/trunk/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/AbstractQuery.java
URL: http://svn.apache.org/viewvc/openjpa/trunk/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/AbstractQuery.java?rev=1203337&view=auto
==============================================================================
--- openjpa/trunk/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/AbstractQuery.java (added)
+++ openjpa/trunk/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/AbstractQuery.java Thu Nov 17 19:13:07 2011
@@ -0,0 +1,641 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.openjpa.persistence;
+
+import java.sql.Time;
+import java.sql.Timestamp;
+import java.util.Calendar;
+import java.util.Collections;
+import java.util.Date;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Map;
+import java.util.Map.Entry;
+import java.util.Set;
+
+import javax.persistence.Parameter;
+import javax.persistence.TemporalType;
+import javax.persistence.TypedQuery;
+import javax.persistence.criteria.ParameterExpression;
+
+import org.apache.openjpa.kernel.Filters;
+import org.apache.openjpa.kernel.QueryLanguages;
+import org.apache.openjpa.lib.util.Localizer;
+import org.apache.openjpa.lib.util.OrderedMap;
+import org.apache.openjpa.meta.QueryMetaData;
+
+/**
+ * An abstract implementation of the Query interface.
+ */
+public abstract class AbstractQuery<X> implements OpenJPAQuerySPI<X> {
+ private static final Localizer _loc = Localizer.forPackage(AbstractQuery.class);
+
+ protected boolean _relaxBindParameterTypeChecking;
+ protected boolean _convertPositionalParams;
+
+ // Will be null if this isn't a NamedQuery
+ protected final QueryMetaData _qmd;
+
+ protected transient EntityManagerImpl _em;
+
+ protected Map<Parameter<?>, Object> _boundParams;
+ protected Map<Object, Parameter<?>> _declaredParams;
+
+ public AbstractQuery(QueryMetaData qmd, EntityManagerImpl em) {
+ _qmd = qmd;
+ _em = em;
+
+ _boundParams = new HashMap<Parameter<?>, Object>();
+ }
+
+ /**
+ * Gets a map of values of each parameter indexed by their <em>original</em> key.
+ *
+ * @return an empty map if no parameter is declared for this query. The unbound parameters has a value of null which
+ * is indistinguishable from the value being bound to null.
+ */
+ Map<Object, Object> getParameterValues() {
+ Map<Object, Object> result = new HashMap<Object, Object>();
+ if (_boundParams == null)
+ return result;
+ for (Map.Entry<Object, Parameter<?>> entry : getDeclaredParameters().entrySet()) {
+ Object paramKey = entry.getKey();
+ Parameter<?> param = entry.getValue();
+ result.put(paramKey, _boundParams.get(param));
+ }
+ return result;
+ }
+
+ public boolean isNative() {
+ return QueryLanguages.LANG_SQL.equals(getLanguage());
+ }
+
+ protected abstract void assertOpen();
+
+ protected abstract void lock();
+
+ protected abstract void unlock();
+
+ /**
+ * @return a map of parameter name to type for this query.
+ */
+ protected abstract OrderedMap<Object, Class<?>> getParamTypes();
+
+ // =================================================================================
+ // Parameter processing routines
+ // =================================================================================
+
+ /**
+ * Binds the parameter identified by the given position to the given value. The parameter are bound to a value in
+ * the context of this query. The same parameter may be bound to a different value in the context of another
+ * query. <br>
+ * For non-native queries, the given position must be a valid position in the declared parameters. <br>
+ * As native queries may not be parsed and hence their declared parameters may not be known, setting an positional
+ * parameter has the side-effect of a positional parameter being declared.
+ *
+ * @param position
+ * positive, integer position of the parameter
+ * @param value
+ * an assignment compatible value
+ * @return the same query instance
+ * @throws IllegalArgumentException
+ * if position does not correspond to a positional parameter of the query or if the argument is of
+ * incorrect type
+ */
+ public OpenJPAQuery<X> setParameter(int pos, Object value) {
+ if (_convertPositionalParams == true) {
+ return setParameter("_" + String.valueOf(pos), value);
+ }
+
+ assertOpen();
+ _em.assertNotCloseInvoked();
+ lock();
+ try {
+ if (pos < 1) {
+ throw new IllegalArgumentException(_loc.get("illegal-index", pos).getMessage());
+ }
+ Parameter<?> param = null;
+ if (isNative()) {
+ param = new ParameterImpl<Object>(pos, Object.class);
+ declareParameter(pos, param);
+ } else {
+ param = getParameter(pos);
+ }
+ bindValue(param, value);
+
+ return this;
+ } finally {
+ unlock();
+ }
+ }
+
+ /**
+ * Sets the value of the given positional parameter after conversion of the given value to the given Temporal Type.
+ */
+ public OpenJPAQuery<X> setParameter(int position, Calendar value, TemporalType t) {
+ return setParameter(position, convertTemporalType(value, t));
+ }
+
+ /**
+ * Sets the value of the given named parameter after conversion of the given value to the given Temporal Type.
+ */
+ public OpenJPAQuery<X> setParameter(int position, Date value, TemporalType type) {
+ return setParameter(position, convertTemporalType(value, type));
+ }
+
+ /**
+ * Converts the given Date to a value corresponding to given temporal type.
+ */
+ Object convertTemporalType(Date value, TemporalType type) {
+ switch (type) {
+ case DATE:
+ return value;
+ case TIME:
+ return new Time(value.getTime());
+ case TIMESTAMP:
+ return new Timestamp(value.getTime());
+ default:
+ return null;
+ }
+ }
+
+ Object convertTemporalType(Calendar value, TemporalType type) {
+ return convertTemporalType(value.getTime(), type);
+ }
+
+ /**
+ * Affirms if declared parameters use position identifier.
+ */
+ public boolean hasPositionalParameters() {
+ return !getDeclaredParameterKeys(Integer.class).isEmpty();
+ }
+
+ /**
+ * Gets the array of positional parameter values. The n-th array element represents (n+1)-th positional parameter.
+ * If a parameter has been declared but not bound to a value then the value is null and hence is indistinguishable
+ * from the value being actually null. If the parameter indexing is not contiguous then the unspecified parameters
+ * are considered as null.
+ */
+ public Object[] getPositionalParameters() {
+ lock();
+ try {
+ Set<Integer> positionalKeys = getDeclaredParameterKeys(Integer.class);
+ Object[] result = new Object[calculateMaxKey(positionalKeys)];
+ for (Integer pos : positionalKeys) {
+ Parameter<?> param = getParameter(pos);
+ result[pos.intValue() - 1] = isBound(param) ? getParameterValue(pos) : null;
+ }
+ return result;
+ } finally {
+ unlock();
+ }
+ }
+
+ /**
+ * Calculate the maximum value of the given set.
+ */
+ int calculateMaxKey(Set<Integer> p) {
+ if (p == null)
+ return 0;
+ int max = Integer.MIN_VALUE;
+ for (Integer i : p)
+ max = Math.max(max, i);
+ return max;
+ }
+
+ /**
+ * Binds the given values as positional parameters. The n-th array element value is set to a Parameter with (n+1)-th
+ * positional identifier.
+ */
+ public OpenJPAQuery<X> setParameters(Object... params) {
+ assertOpen();
+ _em.assertNotCloseInvoked();
+ lock();
+ try {
+ clearBinding();
+ for (int i = 0; params != null && i < params.length; i++) {
+ setParameter(i + 1, params[i]);
+ }
+ return this;
+ } finally {
+ unlock();
+ }
+ }
+
+ void clearBinding() {
+ if (_boundParams != null)
+ _boundParams.clear();
+ }
+
+ /**
+ * Gets the value of all the named parameters.
+ *
+ * If a parameter has been declared but not bound to a value then the value is null and hence is indistinguishable
+ * from the value being actually null.
+ */
+ public Map<String, Object> getNamedParameters() {
+ lock();
+ try {
+ Map<String, Object> result = new HashMap<String, Object>();
+ Set<String> namedKeys = getDeclaredParameterKeys(String.class);
+ for (String name : namedKeys) {
+ Parameter<?> param = getParameter(name);
+ result.put(name, isBound(param) ? getParameterValue(name) : null);
+ }
+ return result;
+ } finally {
+ unlock();
+ }
+ }
+
+ /**
+ * Sets the values of the parameters from the given Map. The keys of the given map designate the name of the
+ * declared parameter.
+ */
+ public OpenJPAQuery<X> setParameters(Map params) {
+ assertOpen();
+ _em.assertNotCloseInvoked();
+ lock();
+ try {
+ clearBinding();
+ if (params != null)
+ for (Map.Entry e : (Set<Map.Entry>) params.entrySet())
+ setParameter((String) e.getKey(), e.getValue());
+ return this;
+ } finally {
+ unlock();
+ }
+ }
+
+ /**
+ * Get the parameter of the given name and type.
+ *
+ * @throws IllegalArgumentException
+ * if the parameter of the specified name does not exist or is not assignable to the type
+ * @throws IllegalStateException
+ * if invoked on a native query
+ */
+ public <T> Parameter<T> getParameter(String name, Class<T> type) {
+ Parameter<?> param = getParameter(name);
+ if (param.getParameterType().isAssignableFrom(type))
+ throw new IllegalArgumentException(param + " does not match the requested type " + type);
+ return (Parameter<T>) param;
+ }
+
+ /**
+ * Get the positional parameter with the given position and type.
+ *
+ * @throws IllegalArgumentException
+ * if the parameter with the specified position does not exist or is not assignable to the type
+ * @throws IllegalStateException
+ * if invoked on a native query unless the same parameter position is bound already.
+ */
+ public <T> Parameter<T> getParameter(int pos, Class<T> type) {
+ if (_convertPositionalParams == true) {
+ return getParameter("_" + String.valueOf(pos), type);
+ }
+ Parameter<?> param = getParameter(pos);
+ if (param.getParameterType().isAssignableFrom(type))
+ throw new IllegalArgumentException(param + " does not match the requested type " + type);
+ return (Parameter<T>) param;
+ }
+
+ /**
+ * Return the value bound to the parameter.
+ *
+ * @param param
+ * parameter object
+ * @return parameter value
+ * @throws IllegalStateException
+ * if the parameter has not been been bound
+ * @throws IllegalArgumentException
+ * if the parameter does not belong to this query
+ */
+ public <T> T getParameterValue(Parameter<T> p) {
+ if (!isBound(p)) {
+ throw new IllegalArgumentException(_loc.get("param-missing", p, getQueryString(), getBoundParameterKeys())
+ .getMessage());
+ }
+ return (T) _boundParams.get(p);
+ }
+
+ /**
+ * Gets the parameters declared in this query.
+ */
+ public Set<Parameter<?>> getParameters() {
+ Set<Parameter<?>> result = new HashSet<Parameter<?>>();
+ result.addAll(getDeclaredParameters().values());
+ return result;
+ }
+
+ public <T> OpenJPAQuery<X> setParameter(Parameter<T> p, T arg1) {
+ bindValue((Parameter<T>) p, arg1);
+ return this;
+ }
+
+ public OpenJPAQuery<X> setParameter(Parameter<Date> p, Date date, TemporalType type) {
+ return setParameter(p, (Date) convertTemporalType(date, type));
+ }
+
+ public TypedQuery<X> setParameter(Parameter<Calendar> p, Calendar cal, TemporalType type) {
+ return setParameter(p, (Calendar) convertTemporalType(cal, type));
+ }
+
+ /**
+ * Get the parameter object corresponding to the declared parameter of the given name. This method is not required
+ * to be supported for native queries.
+ *
+ * @throws IllegalArgumentException
+ * if the parameter of the specified name does not exist
+ * @throws IllegalStateException
+ * if invoked on a native query
+ */
+ public Parameter<?> getParameter(String name) {
+ if (isNative()) {
+ throw new IllegalStateException(_loc.get("param-named-non-native", name).getMessage());
+ }
+ Parameter<?> param = getDeclaredParameters().get(name);
+ if (param == null) {
+ Set<ParameterExpression> exps = getDeclaredParameterKeys(ParameterExpression.class);
+ for (ParameterExpression<?> e : exps) {
+ if (name.equals(e.getName()))
+ return e;
+ }
+ throw new IllegalArgumentException(_loc.get("param-missing-name", name, getQueryString(),
+ getDeclaredParameterKeys()).getMessage());
+ }
+ return param;
+ }
+
+ /**
+ * Get the positional parameter with the given position. The parameter may just have been declared and not bound to
+ * a value.
+ *
+ * @param position
+ * specified in the user query.
+ * @return parameter object
+ * @throws IllegalArgumentException
+ * if the parameter with the given position does not exist
+ */
+ public Parameter<?> getParameter(int pos) {
+ if (_convertPositionalParams == true) {
+ return getParameter("_" + String.valueOf(pos));
+ }
+ Parameter<?> param = getDeclaredParameters().get(pos);
+ if (param == null)
+ throw new IllegalArgumentException(_loc.get("param-missing-pos", pos, getQueryString(),
+ getDeclaredParameterKeys()).getMessage());
+ return param;
+ }
+
+ /**
+ * Return the value bound to the parameter.
+ *
+ * @param name
+ * name of the parameter
+ * @return parameter value
+ *
+ * @throws IllegalStateException
+ * if this parameter has not been bound
+ */
+ public Object getParameterValue(String name) {
+ return _boundParams.get(getParameter(name));
+ }
+
+ /**
+ * Return the value bound to the parameter.
+ *
+ * @param pos
+ * position of the parameter
+ * @return parameter value
+ *
+ * @throws IllegalStateException
+ * if this parameter has not been bound
+ */
+ public Object getParameterValue(int pos) {
+ Parameter<?> param = getParameter(pos);
+ assertBound(param);
+ return _boundParams.get(param);
+ }
+
+ /**
+ * Gets the parameter keys bound with this query. Parameter key can be Integer, String or a ParameterExpression
+ * itself but all parameters keys of a particular query are of the same type.
+ */
+ public Set<?> getBoundParameterKeys() {
+ if (_boundParams == null)
+ return Collections.EMPTY_SET;
+ getDeclaredParameters();
+ Set<Object> result = new HashSet<Object>();
+ for (Map.Entry<Object, Parameter<?>> entry : _declaredParams.entrySet()) {
+ if (isBound(entry.getValue())) {
+ result.add(entry.getKey());
+ }
+ }
+ return result;
+ }
+
+ /**
+ * Gets the declared parameter keys in the given query. This information is only available after the query has been
+ * parsed. As native language queries are not parsed, this information is not available for them.
+ *
+ * @return set of parameter identifiers in a parsed query
+ */
+ public Set<?> getDeclaredParameterKeys() {
+ return getDeclaredParameters().keySet();
+ }
+
+ public <T> Set<T> getDeclaredParameterKeys(Class<T> keyType) {
+ Set<T> result = new HashSet<T>();
+ for (Object key : getDeclaredParameterKeys()) {
+ if (keyType.isInstance(key))
+ result.add((T) key);
+ }
+ return result;
+ }
+
+ /**
+ * Gets the parameter instances declared in this query. All parameter keys are of the same type. It is not allowed
+ * to mix keys of different type such as named and positional keys.
+ *
+ * For string-based queries, the parser supplies the information about the declared parameters as a LinkedMap of
+ * expected parameter value type indexed by parameter identifier. For non string-based queries that a facade itself
+ * may construct (e.g. CriteriaQuery), the parameters must be declared by the caller. This receiver constructs
+ * concrete Parameter instances from the given parameter identifiers.
+ *
+ * @return a Map where the key represents the original identifier of the parameter (can be a String, Integer or a
+ * ParameterExpression itself) and the value is the concrete Parameter instance either constructed as a
+ * result of this call or supplied by declaring the parameter explicitly via
+ * {@linkplain #declareParameter(Parameter)}.
+ */
+ public Map<Object, Parameter<?>> getDeclaredParameters() {
+ if (_declaredParams == null) {
+ _declaredParams = new HashMap<Object, Parameter<?>>();
+
+ OrderedMap<Object, Class<?>> paramTypes = null;
+ // Check to see if we have a cached version of the paramTypes in QueryMetaData.
+ if (_qmd != null) {
+ paramTypes = _qmd.getParamTypes();
+ }
+ if (paramTypes == null) {
+ paramTypes = getParamTypes();
+ // Cache the param types as they haven't been set yet.
+ if (_qmd != null) {
+ _qmd.setParamTypes(paramTypes);
+ }
+ }
+ for (Entry<Object, Class<?>> entry : paramTypes.entrySet()) {
+ Object key = entry.getKey();
+ Class<?> expectedValueType = entry.getValue();
+ Parameter<?> param;
+
+ if (key instanceof Integer) {
+ param = new ParameterImpl((Integer) key, expectedValueType);
+ } else if (key instanceof String) {
+ param = new ParameterImpl((String) key, expectedValueType);
+ } else if (key instanceof Parameter) {
+ param = (Parameter<?>) key;
+ } else {
+ throw new IllegalArgumentException("parameter identifier " + key + " unrecognized");
+ }
+ declareParameter(key, param);
+ }
+ }
+ return _declaredParams;
+ }
+
+ /**
+ * Declares the given parameter for this query. Used by non-string based queries that are constructed by the facade
+ * itself rather than OpenJPA parsing the query to detect the declared parameters.
+ *
+ * @param key
+ * this is the key to identify the parameter later in the context of this query. Valid key types are
+ * Integer, String or ParameterExpression itself.
+ * @param the
+ * parameter instance to be declared
+ */
+ public void declareParameter(Object key, Parameter<?> param) {
+ if (_declaredParams == null) {
+ _declaredParams = new HashMap<Object, Parameter<?>>();
+ }
+ _declaredParams.put(key, param);
+ }
+
+ /**
+ * Affirms if the given parameter is bound to a value for this query.
+ */
+ public boolean isBound(Parameter<?> param) {
+ return _boundParams != null && _boundParams.containsKey(param);
+ }
+
+ void assertBound(Parameter<?> param) {
+ if (!isBound(param)) {
+ throw new IllegalStateException(_loc.get("param-not-bound", param, getQueryString(),
+ getBoundParameterKeys()).getMessage());
+ }
+ }
+
+ /**
+ * Binds the given value to the given parameter. Validates if the parameter can accept the value by its type.
+ */
+ void bindValue(Parameter<?> param, Object value) {
+ Object bindVal = assertValueAssignable(param, value);
+ _boundParams.put(param, bindVal);
+ }
+
+ public OpenJPAQuery<X> setParameter(String name, Calendar value, TemporalType type) {
+ return setParameter(name, convertTemporalType(value, type));
+ }
+
+ public OpenJPAQuery<X> setParameter(String name, Date value, TemporalType type) {
+ return setParameter(name, convertTemporalType(value, type));
+ }
+
+ /**
+ * Sets the parameter of the given name to the given value.
+ */
+ public OpenJPAQuery<X> setParameter(String name, Object value) {
+ assertOpen();
+ _em.assertNotCloseInvoked();
+ lock();
+ try {
+ // native queries can not have named parameters
+ if (isNative()) {
+ throw new IllegalArgumentException(_loc.get("no-named-params", name, getQueryString()).toString());
+ } else {
+ bindValue(getParameter(name), value);
+ }
+
+ return this;
+ } finally {
+ unlock();
+ }
+ }
+
+ /**
+ * 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 (expectedType.isPrimitive())
+ throw new IllegalArgumentException(_loc.get("param-null-primitive", param).getMessage());
+ return v;
+ }
+ 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;
+ }
+ }
+ }
+
+ // ================== End of Parameter Processing routines ================================
+
+ @Override
+ 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();
+ }
+ }
+ }
+}
Modified: openjpa/trunk/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/EntityManagerImpl.java
URL: http://svn.apache.org/viewvc/openjpa/trunk/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/EntityManagerImpl.java?rev=1203337&r1=1203336&r2=1203337&view=diff
==============================================================================
--- openjpa/trunk/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/EntityManagerImpl.java (original)
+++ openjpa/trunk/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/EntityManagerImpl.java Thu Nov 17 19:13:07 2011
@@ -998,7 +998,7 @@ public class EntityManagerImpl
if (pq != null) {
pq.setInto(q);
}
- return newQueryImpl(q).setId(qid);
+ return newQueryImpl(q, null).setId(qid);
} catch (RuntimeException re) {
throw PersistenceExceptions.toPersistenceException(re);
}
@@ -1009,7 +1009,7 @@ public class EntityManagerImpl
return createQuery((String) null);
assertNotCloseInvoked();
org.apache.openjpa.kernel.Query q = ((QueryImpl) query).getDelegate();
- return newQueryImpl(_broker.newQuery(q.getLanguage(), q));
+ return newQueryImpl(_broker.newQuery(q.getLanguage(), q), null);
}
@SuppressWarnings("unchecked")
@@ -1038,7 +1038,7 @@ public class EntityManagerImpl
del.compile();
}
- OpenJPAQuery q = newQueryImpl(del).setId(qid);
+ OpenJPAQuery q = newQueryImpl(del, meta).setId(qid);
String[] hints = meta.getHintKeys();
Object[] values = meta.getHintValues();
for (int i = 0; i < hints.length; i++)
@@ -1064,11 +1064,22 @@ public class EntityManagerImpl
org.apache.openjpa.kernel.Query kernelQuery = _broker.newQuery(
QueryLanguages.LANG_SQL, query);
kernelQuery.setResultMapping(null, mappingName);
- return newQueryImpl(kernelQuery);
+ return newQueryImpl(kernelQuery, null);
}
+ protected <T> QueryImpl<T> newQueryImpl(org.apache.openjpa.kernel.Query kernelQuery, QueryMetaData qmd) {
+ return new QueryImpl<T>(this, _ret, kernelQuery, qmd);
+ }
+
+ /**
+ * @Deprecated -- Use org.apache.openjpa.persistence.EntityManagerImpl.newQueryImpl(Query kernelQuery, QueryMetaData
+ * qmd)
+ * <br>
+ * Leave this method here as extenders of OpenJPA might depend on this hook to allow interception of
+ * query creation
+ */
protected <T> QueryImpl<T> newQueryImpl(org.apache.openjpa.kernel.Query kernelQuery) {
- return new QueryImpl<T>(this, _ret, kernelQuery);
+ return new QueryImpl<T>(this, _ret, kernelQuery, null);
}
/**
@@ -1597,7 +1608,7 @@ public class EntityManagerImpl
org.apache.openjpa.kernel.Query kernelQuery =_broker.newQuery(CriteriaBuilderImpl.LANG_CRITERIA, criteriaQuery);
- QueryImpl<T> facadeQuery = newQueryImpl(kernelQuery).setId(criteriaQuery.toString());
+ QueryImpl<T> facadeQuery = newQueryImpl(kernelQuery, null).setId(criteriaQuery.toString());
Set<ParameterExpression<?>> params = criteriaQuery.getParameters();
for (ParameterExpression<?> param : params) {
Modified: openjpa/trunk/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/ParameterImpl.java
URL: http://svn.apache.org/viewvc/openjpa/trunk/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/ParameterImpl.java?rev=1203337&r1=1203336&r2=1203337&view=diff
==============================================================================
--- openjpa/trunk/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/ParameterImpl.java (original)
+++ openjpa/trunk/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/ParameterImpl.java Thu Nov 17 19:13:07 2011
@@ -48,7 +48,7 @@ public class ParameterImpl<T> implements
* Construct a positional parameter with the given position as key and
* given expected value type.
*/
- public ParameterImpl(int position, Class<T> expectedValueType) {
+ public ParameterImpl(Integer position, Class<T> expectedValueType) {
_name = null;
_position = position;
_expectedValueType = expectedValueType;
@@ -92,6 +92,12 @@ public class ParameterImpl<T> implements
return _position.equals(that.getPosition());
return false;
}
+
+ @Override
+ public int hashCode() {
+ return _expectedValueType.hashCode() ^ ((_name != null) ? _name.hashCode() : 0)
+ ^ ((_position != null) ? _position.hashCode() : 0);
+ }
public String toString() {
StringBuilder buf = new StringBuilder("Parameter");
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=1203337&r1=1203336&r2=1203337&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 Thu Nov 17 19:13:07 2011
@@ -31,8 +31,8 @@ import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
-import java.util.Set;
import java.util.Map.Entry;
+import java.util.Set;
import java.util.concurrent.locks.ReentrantLock;
import javax.persistence.FlushModeType;
@@ -66,6 +66,7 @@ import org.apache.openjpa.lib.log.Log;
import org.apache.openjpa.lib.rop.ResultList;
import org.apache.openjpa.lib.util.Localizer;
import org.apache.openjpa.lib.util.OrderedMap;
+import org.apache.openjpa.meta.QueryMetaData;
import org.apache.openjpa.persistence.criteria.CriteriaBuilderImpl;
import org.apache.openjpa.util.ImplHelper;
import org.apache.openjpa.util.RuntimeExceptionTranslator;
@@ -80,22 +81,15 @@ import org.apache.openjpa.util.UserExcep
* @nojavadoc
*/
@SuppressWarnings("serial")
-public class QueryImpl<X> implements OpenJPAQuerySPI<X>, Serializable {
+public class QueryImpl<X> extends AbstractQuery<X> implements Serializable {
private static final Localizer _loc = Localizer.forPackage(QueryImpl.class);
-
- private DelegatingQuery _query;
- private transient EntityManagerImpl _em;
private transient FetchPlan _fetch;
- private Map<Parameter<?>, Object> _boundParams;
- private Map<Object, Parameter<?>> _declaredParams;
private String _id;
private transient ReentrantLock _lock = null;
private HintHandler _hintHandler;
- private boolean _relaxBindParameterTypeChecking;
- private boolean _convertPositionalParams;
-
+ private DelegatingQuery _query;
/**
* Constructor; supply factory exception translator and delegate.
*
@@ -103,8 +97,9 @@ public class QueryImpl<X> implements Ope
* @param ret Exception translator for this query
* @param query The underlying "kernel" query.
*/
- public QueryImpl(EntityManagerImpl em, RuntimeExceptionTranslator ret, org.apache.openjpa.kernel.Query query) {
- _em = em;
+ public QueryImpl(EntityManagerImpl em, RuntimeExceptionTranslator ret, org.apache.openjpa.kernel.Query query,
+ QueryMetaData qmd) {
+ super(qmd, em);
_query = new DelegatingQuery(query, ret);
_lock = new ReentrantLock();
if(query.getLanguage() == QueryLanguages.LANG_SQL) {
@@ -123,7 +118,7 @@ public class QueryImpl<X> implements Ope
* @deprecated
*/
public QueryImpl(EntityManagerImpl em, org.apache.openjpa.kernel.Query query) {
- this(em, null, query);
+ this(em, null, query, null);
}
/**
@@ -266,45 +261,12 @@ public class QueryImpl<X> implements Ope
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();
_query.compile();
return this;
}
- /**
- * Gets a map of values of each parameter indexed by their <em>original</em> key.
- *
- * @return an empty map if no parameter is declared for this query.
- * The unbound parameters has a value of null which is indistinguishable
- * from the value being bound to null.
- */
- Map<Object,Object> getParameterValues() {
- Map<Object,Object> result = new HashMap<Object,Object>();
- if (_boundParams == null)
- return result;
- for (Map.Entry<Object,Parameter<?>> entry : getDeclaredParameters().entrySet()) {
- Object paramKey = entry.getKey();
- Parameter<?> param = entry.getValue();
- result.put(paramKey, _boundParams.get(param));
- }
- return result;
- }
-
private Object execute() {
if (!isNative() && _query.getOperation() != QueryOperations.OP_SELECT)
throw new InvalidStateException(_loc.get("not-select-query", getQueryString()), null, null, false);
@@ -431,10 +393,6 @@ public class QueryImpl<X> implements Ope
return this;
}
- public boolean isNative() {
- return QueryLanguages.LANG_SQL.equals(getLanguage());
- }
-
/**
* Asserts that this query is a JPQL or Criteria Query.
*/
@@ -652,531 +610,26 @@ public class QueryImpl<X> implements Ope
}
// ================ End of Prepared Query related methods =====================
- void lock() {
+ protected void lock() {
if (_lock != null)
_lock.lock();
}
- void unlock() {
+ protected void unlock() {
if (_lock != null)
_lock.unlock();
}
-
- // =================================================================================
- // Parameter processing routines
- // =================================================================================
-
- /**
- * Binds the parameter identified by the given position to the given value.
- * The parameter are bound to a value in the context of this query.
- * The same parameter may be bound to a different value in the context of
- * another query.
- * <br>
- * For non-native queries, the given position must be a valid position in
- * the declared parameters.
- * <br>
- * As native queries may not be parsed and hence their declared parameters
- * may not be known, setting an positional parameter has the side-effect
- * of a positional parameter being declared.
- *
- * @param position positive, integer position of the parameter
- * @param value an assignment compatible value
- * @return the same query instance
- * @throws IllegalArgumentException if position does not correspond to a positional
- * parameter of the query or if the argument is of incorrect type
- */
- public OpenJPAQuery<X> setParameter(int pos, Object value) {
- if (_convertPositionalParams == true) {
- return setParameter("_"+String.valueOf(pos), value);
- }
-
- _query.assertOpen();
- _em.assertNotCloseInvoked();
- _query.lock();
- try {
- if (pos < 1) {
- throw new IllegalArgumentException(_loc.get("illegal-index", pos).getMessage());
- }
- Parameter<?> param = null;
- if (isNative()) {
- param = new ParameterImpl<Object>(pos, Object.class);
- declareParameter(pos, param);
- } else {
- param = getParameter(pos);
- }
- bindValue(param, value);
-
- return this;
- } finally {
- _query.unlock();
- }
- }
-
- /**
- * Sets the value of the given positional parameter after conversion of the
- * given value to the given Temporal Type.
- */
- public OpenJPAQuery<X> setParameter(int position, Calendar value, TemporalType t) {
- return setParameter(position, convertTemporalType(value, t));
- }
-
- /**
- * Sets the value of the given named parameter after conversion of the
- * given value to the given Temporal Type.
- */
- public OpenJPAQuery<X> setParameter(int position, Date value, TemporalType type) {
- return setParameter(position, convertTemporalType(value, type));
- }
-
- /**
- * Converts the given Date to a value corresponding to given temporal type.
- */
- Object convertTemporalType(Date value, TemporalType type) {
- switch (type) {
- case DATE:
- return value;
- case TIME:
- return new Time(value.getTime());
- case TIMESTAMP:
- return new Timestamp(value.getTime());
- default:
- return null;
- }
- }
-
- Object convertTemporalType(Calendar value, TemporalType type) {
- return convertTemporalType(value.getTime(), type);
- }
-
- /**
- * Affirms if declared parameters use position identifier.
- */
- public boolean hasPositionalParameters() {
- return !getDeclaredParameterKeys(Integer.class).isEmpty();
- }
-
- /**
- * Gets the array of positional parameter values.
- * The n-th array element represents (n+1)-th positional parameter.
- * If a parameter has been declared but not bound to a value then
- * the value is null and hence is indistinguishable from the value
- * being actually null.
- * If the parameter indexing is not contiguous then the unspecified
- * parameters are considered as null.
- */
- public Object[] getPositionalParameters() {
- _query.lock();
- try {
- Set<Integer> positionalKeys = getDeclaredParameterKeys(Integer.class);
- Object[] result = new Object[calculateMaxKey(positionalKeys)];
- for (Integer pos : positionalKeys) {
- Parameter<?> param = getParameter(pos);
- result[pos.intValue()-1] = isBound(param) ? getParameterValue(pos) : null;
- }
- return result;
- } finally {
- _query.unlock();
- }
- }
-
- /**
- * Calculate the maximum value of the given set.
- */
- int calculateMaxKey(Set<Integer> p) {
- if (p == null)
- return 0;
- int max = Integer.MIN_VALUE;
- for (Integer i : p)
- max = Math.max(max, i);
- return max;
- }
-
- /**
- * Binds the given values as positional parameters.
- * The n-th array element value is set to a Parameter with (n+1)-th positional identifier.
- */
- public OpenJPAQuery<X> setParameters(Object... params) {
- _query.assertOpen();
- _em.assertNotCloseInvoked();
- _query.lock();
- try {
- clearBinding();
- for (int i = 0; params != null && i < params.length; i++) {
- setParameter(i + 1, params[i]);
- }
- return this;
- } finally {
- _query.unlock();
- }
- }
-
- void clearBinding() {
- if (_boundParams != null)
- _boundParams.clear();
- }
-
- /**
- * Gets the value of all the named parameters.
- *
- * If a parameter has been declared but not bound to a value then
- * the value is null and hence is indistinguishable from the value
- * being actually null.
- */
- public Map<String, Object> getNamedParameters() {
- _query.lock();
- try {
- Map<String, Object> result = new HashMap<String, Object>();
- Set<String> namedKeys = getDeclaredParameterKeys(String.class);
- for (String name : namedKeys) {
- Parameter<?> param = getParameter(name);
- result.put(name, isBound(param) ? getParameterValue(name) : null);
- }
- return result;
- } finally {
- _query.unlock();
- }
- }
-
- /**
- * Sets the values of the parameters from the given Map.
- * The keys of the given map designate the name of the declared parameter.
-
- */
- public OpenJPAQuery<X> setParameters(Map params) {
+ @Override
+ protected void assertOpen() {
_query.assertOpen();
- _em.assertNotCloseInvoked();
- _query.lock();
- try {
- clearBinding();
- if (params != null)
- for (Map.Entry e : (Set<Map.Entry>) params.entrySet())
- setParameter((String) e.getKey(), e.getValue());
- return this;
- } finally {
- _query.unlock();
- }
- }
-
- /**
- * Get the parameter of the given name and type.
- *
- * @throws IllegalArgumentException if the parameter of the
- * specified name does not exist or is not assignable
- * to the type
- * @throws IllegalStateException if invoked on a native query
- */
- public <T> Parameter<T> getParameter(String name, Class<T> type) {
- Parameter<?> param = getParameter(name);
- if (param.getParameterType().isAssignableFrom(type))
- throw new IllegalArgumentException(param + " does not match the requested type " + type);
- return (Parameter<T>)param;
- }
-
- /**
- * Get the positional parameter with the given position and type.
- * @throws IllegalArgumentException if the parameter with the
- * specified position does not exist or is not assignable
- * to the type
- * @throws IllegalStateException if invoked on a native query unless
- * the same parameter position is bound already.
- */
- public <T> Parameter<T> getParameter(int pos, Class<T> type) {
- if (_convertPositionalParams == true) {
- return getParameter("_"+String.valueOf(pos), type);
- }
- Parameter<?> param = getParameter(pos);
- if (param.getParameterType().isAssignableFrom(type))
- throw new IllegalArgumentException(param + " does not match the requested type " + type);
- return (Parameter<T>)param;
}
- /**
- * Return the value bound to the parameter.
- * @param param parameter object
- * @return parameter value
- * @throws IllegalStateException if the parameter has not been been bound
- * @throws IllegalArgumentException if the parameter does not belong to this query
- */
- public <T> T getParameterValue(Parameter<T> p) {
- if (!isBound(p)) {
- throw new IllegalArgumentException(_loc.get("param-missing", p, getQueryString(),
- getBoundParameterKeys()).getMessage());
- }
- return (T)_boundParams.get(p);
+ @Override
+ public OrderedMap<Object, Class<?>> getParamTypes() {
+ return _query.getOrderedParameterTypes();
}
- /**
- * Gets the parameters declared in this query.
- */
- public Set<Parameter<?>> getParameters() {
- Set<Parameter<?>> result = new HashSet<Parameter<?>>();
- result.addAll(getDeclaredParameters().values());
- return result;
- }
-
- public <T> OpenJPAQuery<X> setParameter(Parameter<T> p, T arg1) {
- bindValue((Parameter<T>)p, arg1);
- return this;
- }
-
- public OpenJPAQuery<X> setParameter(Parameter<Date> p, Date date, TemporalType type) {
- return setParameter(p, (Date)convertTemporalType(date, type));
- }
-
- public TypedQuery<X> setParameter(Parameter<Calendar> p, Calendar cal, TemporalType type) {
- return setParameter(p, (Calendar)convertTemporalType(cal, type));
- }
-
- /**
- * Get the parameter object corresponding to the declared parameter of the given name.
- * This method is not required to be supported for native queries.
- *
- * @throws IllegalArgumentException if the parameter of the specified name does not exist
- * @throws IllegalStateException if invoked on a native query
- */
- public Parameter<?> getParameter(String name) {
- if (isNative()) {
- throw new IllegalStateException(_loc.get("param-named-non-native", name).getMessage());
- }
- Parameter<?> param = getDeclaredParameters().get(name);
- if (param == null) {
- Set<ParameterExpression> exps = getDeclaredParameterKeys(ParameterExpression.class);
- for (ParameterExpression<?> e : exps) {
- if (name.equals(e.getName()))
- return e;
- }
- throw new IllegalArgumentException(_loc.get("param-missing-name",
- name, getQueryString(), getDeclaredParameterKeys()).getMessage());
- }
- return param;
- }
-
- /**
- * Get the positional parameter with the given position.
- * The parameter may just have been declared and not bound to a value.
- *
- * @param position specified in the user query.
- * @return parameter object
- * @throws IllegalArgumentException if the parameter with the given position does not exist
- */
- public Parameter<?> getParameter(int pos) {
- if(_convertPositionalParams == true){
- return getParameter("_"+String.valueOf(pos));
- }
- Parameter<?> param = getDeclaredParameters().get(pos);
- if (param == null)
- throw new IllegalArgumentException(_loc.get("param-missing-pos",
- pos, getQueryString(), getDeclaredParameterKeys()).getMessage());
- return param;
- }
-
- /**
- * Return the value bound to the parameter.
- *
- * @param name name of the parameter
- * @return parameter value
- *
- * @throws IllegalStateException if this parameter has not been bound
- */
- public Object getParameterValue(String name) {
- return _boundParams.get(getParameter(name));
- }
-
- /**
- * Return the value bound to the parameter.
- *
- * @param pos position of the parameter
- * @return parameter value
- *
- * @throws IllegalStateException if this parameter has not been bound
- */
- public Object getParameterValue(int pos) {
- Parameter<?> param = getParameter(pos);
- assertBound(param);
- return _boundParams.get(param);
- }
-
- /**
- * Gets the parameter keys bound with this query.
- * Parameter key can be Integer, String or a ParameterExpression itself
- * but all parameters keys of a particular query are of the same type.
- */
- public Set<?> getBoundParameterKeys() {
- if (_boundParams == null)
- return Collections.EMPTY_SET;
- getDeclaredParameters();
- Set<Object> result = new HashSet<Object>();
- for (Map.Entry<Object, Parameter<?>> entry : _declaredParams.entrySet()) {
- if (isBound(entry.getValue())) {
- result.add(entry.getKey());
- }
- }
- return result;
- }
-
- /**
- * Gets the declared parameter keys in the given query.
- * This information is only available after the query has been parsed.
- * As native language queries are not parsed, this information is not available for them.
- *
- * @return set of parameter identifiers in a parsed query
- */
- public Set<?> getDeclaredParameterKeys() {
- return getDeclaredParameters().keySet();
- }
-
- public <T> Set<T> getDeclaredParameterKeys(Class<T> keyType) {
- Set<T> result = new HashSet<T>();
- for (Object key : getDeclaredParameterKeys()) {
- if (keyType.isInstance(key))
- result.add((T)key);
- }
- return result;
- }
-
- /**
- * Gets the parameter instances declared in this query.
- * All parameter keys are of the same type. It is not allowed to mix keys of different type
- * such as named and positional keys.
- *
- * For string-based queries, the parser supplies the information about the declared parameters
- * as a LinkedMap of expected parameter value type indexed by parameter identifier.
- * For non string-based queries that a facade itself may construct (e.g. CriteriaQuery),
- * the parameters must be declared by the caller.
- * This receiver constructs concrete Parameter instances from the given parameter identifiers.
- *
- * @return a Map where the key represents the original identifier of the parameter (can be a String,
- * Integer or a ParameterExpression itself) and the value is the concrete Parameter instance
- * either constructed as a result of this call or supplied by declaring the parameter explicitly
- * via {@linkplain #declareParameter(Parameter)}.
- */
- public Map<Object, Parameter<?>> getDeclaredParameters() {
- if (_declaredParams == null) {
- _declaredParams = new HashMap<Object, Parameter<?>>();
- OrderedMap<Object,Class<?>> paramTypes = _query.getOrderedParameterTypes();
- for(Entry<Object,Class<?>> entry : paramTypes.entrySet()){
- Object key = entry.getKey();
- Class<?> expectedValueType = entry.getValue();
- Parameter<?> param;
-
- if (key instanceof Integer) {
- param = new ParameterImpl((Integer)key, expectedValueType);
- } else if (key instanceof String) {
- param = new ParameterImpl((String)key, expectedValueType);
- } else if (key instanceof Parameter) {
- param = (Parameter<?>)key;
- } else {
- throw new IllegalArgumentException("parameter identifier " + key + " unrecognized");
- }
- declareParameter(key, param);
- }
- }
- return _declaredParams;
- }
-
- /**
- * Declares the given parameter for this query.
- * Used by non-string based queries that are constructed by the facade itself rather than
- * OpenJPA parsing the query to detect the declared parameters.
- *
- * @param key this is the key to identify the parameter later in the context of this query.
- * Valid key types are Integer, String or ParameterExpression itself.
- * @param the parameter instance to be declared
- */
- public void declareParameter(Object key, Parameter<?> param) {
- if (_declaredParams == null) {
- _declaredParams = new HashMap<Object, Parameter<?>>();
- }
- _declaredParams.put(key, param);
- }
-
- /**
- * Affirms if the given parameter is bound to a value for this query.
- */
- public boolean isBound(Parameter<?> param) {
- return _boundParams != null && _boundParams.containsKey(param);
- }
-
- void assertBound(Parameter<?> param) {
- if (!isBound(param)) {
- throw new IllegalStateException(_loc.get("param-not-bound", param, getQueryString(),
- getBoundParameterKeys()).getMessage());
- }
- }
- /**
- * Binds the given value to the given parameter.
- * Validates if the parameter can accept the value by its type.
- */
- void bindValue(Parameter<?> param, Object value) {
- Object bindVal = assertValueAssignable(param, value);
- if (_boundParams == null)
- _boundParams = new HashMap<Parameter<?>, Object>();
- _boundParams.put(param, bindVal);
- }
-
- public OpenJPAQuery<X> setParameter(String name, Calendar value, TemporalType type) {
- return setParameter(name, convertTemporalType(value, type));
- }
-
- public OpenJPAQuery<X> setParameter(String name, Date value, TemporalType type) {
- return setParameter(name, convertTemporalType(value, type));
- }
-
- /**
- * Sets the parameter of the given name to the given value.
- */
- public OpenJPAQuery<X> setParameter(String name, Object value) {
- _query.assertOpen();
- _em.assertNotCloseInvoked();
- _query.lock();
- try {
- // native queries can not have named parameters
- if (isNative()) {
- throw new IllegalArgumentException(_loc.get("no-named-params",
- name, getQueryString()).toString());
- } else {
- bindValue(getParameter(name), value);
- }
-
- return this;
- } finally {
- _query.unlock();
- }
- }
-
- /**
- * 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 (expectedType.isPrimitive())
- throw new IllegalArgumentException(_loc.get("param-null-primitive", param).getMessage());
- return v;
- }
- 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;
- }
- }
- }
-
- // ================== End of Parameter Processing routines ================================
-
public String toString() {
String result = _query.getQueryString();
return result != null ? result : _id;