mirror of
https://github.com/apache/openjpa.git
synced 2025-02-21 01:15:30 +00:00
OPENJPA-1999: Optional support for non-sequential positional parameters - used Rick's provided patch for trunk.
git-svn-id: https://svn.apache.org/repos/asf/openjpa/trunk@1134128 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
parent
b9e61a8923
commit
cabf34a6fd
@ -69,6 +69,7 @@ public class Compatibility {
|
||||
private boolean _checkDatabaseForCascadePersistToDetachedEntity = false;
|
||||
private boolean _overrideContextClassloader = true;
|
||||
private boolean _parseAnnotationsForQueryMode = true;
|
||||
private boolean _convertPositionalParametersToNamed = false;
|
||||
|
||||
/**
|
||||
* Whether to require exact identity value types when creating object
|
||||
@ -330,6 +331,14 @@ public class Compatibility {
|
||||
public boolean getIgnoreDetachedStateFieldForProxySerialization() {
|
||||
return _ignoreDetachedStateFieldForProxySerialization;
|
||||
}
|
||||
|
||||
public boolean getConvertPositionalParametersToNamed() {
|
||||
return _convertPositionalParametersToNamed;
|
||||
}
|
||||
|
||||
public void setConvertPositionalParametersToNamed(boolean c) {
|
||||
_convertPositionalParametersToNamed = c;
|
||||
}
|
||||
|
||||
/**
|
||||
* Whether OpenJPA should flush changes before detaching or serializing an
|
||||
|
@ -2038,7 +2038,8 @@ public class MetaDataRepository implements PCRegistry.RegisterClassListener, Con
|
||||
* Create a new query metadata instance.
|
||||
*/
|
||||
protected QueryMetaData newQueryMetaData(Class<?> cls, String name) {
|
||||
QueryMetaData meta = new QueryMetaData(name);
|
||||
QueryMetaData meta =
|
||||
new QueryMetaData(name, _conf.getCompatibilityInstance().getConvertPositionalParametersToNamed());
|
||||
meta.setDefiningType(cls);
|
||||
return meta;
|
||||
}
|
||||
|
@ -25,6 +25,8 @@ import java.util.List;
|
||||
|
||||
import org.apache.commons.lang.StringUtils;
|
||||
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.xml.Commentable;
|
||||
|
||||
@ -59,12 +61,14 @@ public class QueryMetaData
|
||||
private int _lineNum;
|
||||
private int _colNum;
|
||||
private String _srcName;
|
||||
private boolean _convertPositionalParametersToNamed;
|
||||
|
||||
/**
|
||||
* Construct with the given name.
|
||||
*/
|
||||
protected QueryMetaData(String name) {
|
||||
protected QueryMetaData(String name, boolean convertPositionalParametersToNamed) {
|
||||
_name = name;
|
||||
_convertPositionalParametersToNamed = convertPositionalParametersToNamed;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -155,6 +159,9 @@ public class QueryMetaData
|
||||
* The full query string, or null if none.
|
||||
*/
|
||||
public void setQueryString(String query) {
|
||||
if (query != null && _convertPositionalParametersToNamed && JPQLParser.LANG_JPQL.equals(_language)) {
|
||||
query = query.replaceAll("[\\?]", "\\:_");
|
||||
}
|
||||
_query = query;
|
||||
}
|
||||
|
||||
|
@ -44,7 +44,9 @@ import javax.persistence.Table;
|
||||
query="select a from simple a where a.id=:id and a.name=:name"),
|
||||
@NamedQuery(name="FindOne",
|
||||
query="select s from simple s where s.name = ?1"),
|
||||
@NamedQuery(name="FindAll", query="select s from simple s")
|
||||
@NamedQuery(name="FindAll", query="select s from simple s"),
|
||||
@NamedQuery(name="SelectWithPositionalParameterNonOneStart",
|
||||
query="select a from simple a where a.id=?900 and a.name=?2")
|
||||
})
|
||||
|
||||
@NamedNativeQueries( {
|
||||
|
@ -0,0 +1,75 @@
|
||||
/*
|
||||
* 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.query;
|
||||
|
||||
import javax.persistence.EntityManager;
|
||||
|
||||
import org.apache.openjpa.persistence.test.SingleEMFTestCase;
|
||||
|
||||
/**
|
||||
* This test was added for OPENJPA-1999. 'Add' support for allowing positional parameters to start at something other
|
||||
* than 1 and allow for missing parameters.
|
||||
*/
|
||||
public class TestQueryConvertPositionalParameters extends SingleEMFTestCase {
|
||||
EntityManager _em;
|
||||
long _id;
|
||||
String _name;
|
||||
|
||||
@Override
|
||||
public void setUp() {
|
||||
super.setUp(SimpleEntity.class, "openjpa.Compatibility", "ConvertPositionalParametersToNamed=true");
|
||||
_em = emf.createEntityManager();
|
||||
|
||||
_em.getTransaction().begin();
|
||||
SimpleEntity se = new SimpleEntity();
|
||||
_name = "name--" + System.currentTimeMillis();
|
||||
se.setName(_name);
|
||||
_em.persist(se);
|
||||
_em.getTransaction().commit();
|
||||
_id = se.getId();
|
||||
_em.clear();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void tearDown() throws Exception {
|
||||
if (_em.getTransaction().isActive()) {
|
||||
_em.getTransaction().rollback();
|
||||
}
|
||||
_em.close();
|
||||
// TODO Auto-generated method stub
|
||||
super.tearDown();
|
||||
}
|
||||
|
||||
public void testNamedPositionalStartAtNonOne() {
|
||||
SimpleEntity se =
|
||||
_em.createNamedQuery("SelectWithPositionalParameterNonOneStart", SimpleEntity.class).setParameter(900, _id)
|
||||
.setParameter(2, _name).getSingleResult();
|
||||
assertNotNull(se);
|
||||
}
|
||||
|
||||
public void testJPQLPositionalStartAtNonOne() {
|
||||
int idPos = 7;
|
||||
int namePos = 908;
|
||||
SimpleEntity se =
|
||||
_em.createQuery("Select s FROM simple s where s.id=?" + idPos + " and s.name=?" + namePos,
|
||||
SimpleEntity.class).setParameter(idPos, _id).setParameter(namePos, _name).getSingleResult();
|
||||
assertNotNull(se);
|
||||
}
|
||||
|
||||
}
|
@ -1822,8 +1822,8 @@ public class AnnotationPersistenceMetaDataParser
|
||||
continue;
|
||||
}
|
||||
meta = getRepository().addQueryMetaData(_cls, query.name());
|
||||
meta.setQueryString(query.query());
|
||||
meta.setLanguage(JPQLParser.LANG_JPQL);
|
||||
meta.setQueryString(query.query());
|
||||
for (QueryHint hint : query.hints())
|
||||
meta.addHint(hint.name(), hint.value());
|
||||
LockModeType lmt = processNamedQueryLockModeType(query);
|
||||
@ -1895,8 +1895,8 @@ public class AnnotationPersistenceMetaDataParser
|
||||
}
|
||||
|
||||
meta = getRepository().addQueryMetaData(null, query.name());
|
||||
meta.setQueryString(query.query());
|
||||
meta.setLanguage(QueryLanguages.LANG_SQL);
|
||||
meta.setQueryString(query.query());
|
||||
Class<?> res = query.resultClass();
|
||||
if (ImplHelper.isManagedType(getConfiguration(), res))
|
||||
meta.setCandidateType(res);
|
||||
|
@ -113,7 +113,8 @@ public class EntityManagerImpl
|
||||
private EntityManagerFactoryImpl _emf;
|
||||
private Map<FetchConfiguration,FetchPlan> _plans = new IdentityHashMap<FetchConfiguration,FetchPlan>(1);
|
||||
protected RuntimeExceptionTranslator _ret = PersistenceExceptions.getRollbackTranslator(this);
|
||||
|
||||
private boolean _convertPositionalParams = false;
|
||||
|
||||
public EntityManagerImpl() {
|
||||
// for Externalizable
|
||||
}
|
||||
@ -129,6 +130,9 @@ public class EntityManagerImpl
|
||||
_emf = factory;
|
||||
_broker = new DelegatingBroker(broker, _ret);
|
||||
_broker.setImplicitBehavior(this, _ret);
|
||||
|
||||
_convertPositionalParams =
|
||||
factory.getConfiguration().getCompatibilityInstance().getConvertPositionalParametersToNamed();
|
||||
}
|
||||
|
||||
/**
|
||||
@ -977,6 +981,10 @@ public class EntityManagerImpl
|
||||
public OpenJPAQuery createQuery(String language, String query) {
|
||||
assertNotCloseInvoked();
|
||||
try {
|
||||
// We need
|
||||
if (query != null && _convertPositionalParams && JPQLParser.LANG_JPQL.equals(language)) {
|
||||
query = query.replaceAll("[\\?]", "\\:_");
|
||||
}
|
||||
String qid = query;
|
||||
PreparedQuery pq = JPQLParser.LANG_JPQL.equals(language)
|
||||
? getPreparedQuery(qid) : null;
|
||||
@ -1017,11 +1025,10 @@ public class EntityManagerImpl
|
||||
_broker.getClassLoader(), true);
|
||||
String qid = meta.getQueryString();
|
||||
|
||||
PreparedQuery pq = JPQLParser.LANG_JPQL.equals(meta.getLanguage())
|
||||
? getPreparedQuery(qid) : null;
|
||||
org.apache.openjpa.kernel.Query del = (pq == null || !pq.isInitialized())
|
||||
? _broker.newQuery(meta.getLanguage(), meta.getQueryString())
|
||||
: _broker.newQuery(pq.getLanguage(), pq);
|
||||
PreparedQuery pq = JPQLParser.LANG_JPQL.equals(meta.getLanguage()) ? getPreparedQuery(qid) : null;
|
||||
org.apache.openjpa.kernel.Query del =
|
||||
(pq == null || !pq.isInitialized()) ? _broker.newQuery(meta.getLanguage(), meta.getQueryString())
|
||||
: _broker.newQuery(pq.getLanguage(), pq);
|
||||
|
||||
if (pq != null) {
|
||||
pq.setInto(del);
|
||||
@ -1060,7 +1067,8 @@ public class EntityManagerImpl
|
||||
}
|
||||
|
||||
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, _convertPositionalParams
|
||||
&& !kernelQuery.getLanguage().equals(QueryLanguages.LANG_SQL));
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -93,6 +93,7 @@ public class QueryImpl<X> implements OpenJPAQuerySPI<X>, Serializable {
|
||||
private transient ReentrantLock _lock = null;
|
||||
private HintHandler _hintHandler;
|
||||
private boolean _relaxBindParameterTypeChecking;
|
||||
final private boolean _convertPositionalParams;
|
||||
|
||||
/**
|
||||
* Constructor; supply factory exception translator and delegate.
|
||||
@ -101,19 +102,21 @@ public class QueryImpl<X> implements OpenJPAQuerySPI<X>, Serializable {
|
||||
* @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;
|
||||
_query = new DelegatingQuery(query, ret);
|
||||
_lock = new ReentrantLock();
|
||||
}
|
||||
public QueryImpl(EntityManagerImpl em, RuntimeExceptionTranslator ret, org.apache.openjpa.kernel.Query query,
|
||||
boolean convertPositionalParams) {
|
||||
_em = em;
|
||||
_query = new DelegatingQuery(query, ret);
|
||||
_lock = new ReentrantLock();
|
||||
_convertPositionalParams = convertPositionalParams;
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructor; supply factory and delegate.
|
||||
*
|
||||
* @deprecated
|
||||
*/
|
||||
public QueryImpl(EntityManagerImpl em, org.apache.openjpa.kernel.Query query) {
|
||||
this(em, null, query);
|
||||
public QueryImpl(EntityManagerImpl em, org.apache.openjpa.kernel.Query query, boolean convertPositionalParams) {
|
||||
this(em, null, query, convertPositionalParams);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -677,6 +680,10 @@ public class QueryImpl<X> implements OpenJPAQuerySPI<X>, Serializable {
|
||||
* 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();
|
||||
@ -868,6 +875,9 @@ public class QueryImpl<X> implements OpenJPAQuerySPI<X>, Serializable {
|
||||
* 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);
|
||||
@ -944,6 +954,9 @@ public class QueryImpl<X> implements OpenJPAQuerySPI<X>, Serializable {
|
||||
* @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",
|
||||
|
@ -1704,8 +1704,8 @@ public class XMLPersistenceMetaDataParser
|
||||
|
||||
meta = getRepository().addQueryMetaData(null, name);
|
||||
meta.setDefiningType(_cls);
|
||||
meta.setQueryString(attrs.getValue("query"));
|
||||
meta.setLanguage(JPQLParser.LANG_JPQL);
|
||||
meta.setQueryString(attrs.getValue("query"));
|
||||
String lockModeStr = attrs.getValue("lock-mode");
|
||||
LockModeType lmt = processNamedQueryLockModeType(log, lockModeStr, name);
|
||||
if (lmt != null) {
|
||||
@ -1808,8 +1808,8 @@ public class XMLPersistenceMetaDataParser
|
||||
|
||||
meta = getRepository().addQueryMetaData(null, name);
|
||||
meta.setDefiningType(_cls);
|
||||
meta.setQueryString(attrs.getValue("query"));
|
||||
meta.setLanguage(QueryLanguages.LANG_SQL);
|
||||
meta.setQueryString(attrs.getValue("query"));
|
||||
String val = attrs.getValue("result-class");
|
||||
if (val != null) {
|
||||
Class<?> type = classForName(val);
|
||||
|
Loading…
x
Reference in New Issue
Block a user