Modified: openjpa/branches/openjpa_jpa-2.1/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/AnnotationPersistenceMetaDataParser.java URL: http://svn.apache.org/viewvc/openjpa/branches/openjpa_jpa-2.1/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/AnnotationPersistenceMetaDataParser.java?rev=1683972&r1=1683971&r2=1683972&view=diff ============================================================================== --- openjpa/branches/openjpa_jpa-2.1/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/AnnotationPersistenceMetaDataParser.java (original) +++ openjpa/branches/openjpa_jpa-2.1/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/AnnotationPersistenceMetaDataParser.java Sun Jun 7 01:05:22 2015 @@ -63,6 +63,8 @@ import static org.apache.openjpa.persist import static org.apache.openjpa.persistence.MetaDataTag.QUERY; import static org.apache.openjpa.persistence.MetaDataTag.READ_ONLY; import static org.apache.openjpa.persistence.MetaDataTag.SEQ_GENERATOR; +import static org.apache.openjpa.persistence.MetaDataTag.STOREDPROCEDURE_QUERIES; +import static org.apache.openjpa.persistence.MetaDataTag.STOREDPROCEDURE_QUERY; import static org.apache.openjpa.persistence.MetaDataTag.TYPE; import static org.apache.openjpa.persistence.MetaDataTag.VERSION; @@ -120,9 +122,12 @@ import javax.persistence.NamedNativeQuer import javax.persistence.NamedNativeQuery; import javax.persistence.NamedQueries; import javax.persistence.NamedQuery; +import javax.persistence.NamedStoredProcedureQueries; +import javax.persistence.NamedStoredProcedureQuery; import javax.persistence.OneToMany; import javax.persistence.OneToOne; import javax.persistence.OrderBy; +import javax.persistence.ParameterMode; import javax.persistence.PostLoad; import javax.persistence.PostPersist; import javax.persistence.PostRemove; @@ -132,6 +137,7 @@ import javax.persistence.PreRemove; import javax.persistence.PreUpdate; import javax.persistence.QueryHint; import javax.persistence.SequenceGenerator; +import javax.persistence.StoredProcedureParameter; import javax.persistence.Version; import org.apache.commons.lang.StringUtils; @@ -156,6 +162,7 @@ import org.apache.openjpa.meta.Lifecycle import org.apache.openjpa.meta.MetaDataFactory; import org.apache.openjpa.meta.MetaDataModes; import org.apache.openjpa.meta.MetaDataRepository; +import org.apache.openjpa.meta.MultiQueryMetaData; import org.apache.openjpa.meta.Order; import org.apache.openjpa.meta.QueryMetaData; import org.apache.openjpa.meta.SequenceMetaData; @@ -203,6 +210,8 @@ public class AnnotationPersistenceMetaDa _tags.put(MapsId.class, MAPPED_BY_ID); _tags.put(NamedNativeQueries.class, NATIVE_QUERIES); _tags.put(NamedNativeQuery.class, NATIVE_QUERY); + _tags.put(NamedStoredProcedureQueries.class, STOREDPROCEDURE_QUERIES); + _tags.put(NamedStoredProcedureQuery.class, STOREDPROCEDURE_QUERY); _tags.put(NamedQueries.class, QUERIES); _tags.put(NamedQuery.class, QUERY); _tags.put(OrderBy.class, ORDER_BY); @@ -471,6 +480,14 @@ public class AnnotationPersistenceMetaDa if (isQueryMode() && (pkgMode & MODE_QUERY) == 0) parseNamedQueries(pkg, (NamedQuery) anno); break; + case STOREDPROCEDURE_QUERIES: + if (isQueryMode()) + parseNamedStoredProcedureQueries(pkg, ((NamedStoredProcedureQueries) anno).value()); + break; + case STOREDPROCEDURE_QUERY: + if (isQueryMode()) + parseNamedStoredProcedureQueries(pkg, ((NamedStoredProcedureQuery) anno)); + break; case SEQ_GENERATOR: if (isMappingOverrideMode() && (pkgMode & MODE_MAPPING) == 0) @@ -623,6 +640,14 @@ public class AnnotationPersistenceMetaDa if (isQueryMode() && (meta.getSourceMode() & MODE_QUERY)==0) parseNamedQueries(_cls, (NamedQuery) anno); break; + case STOREDPROCEDURE_QUERIES: + if (isQueryMode()) + parseNamedStoredProcedureQueries(_cls, ((NamedStoredProcedureQueries) anno).value()); + break; + case STOREDPROCEDURE_QUERY: + if (isQueryMode()) + parseNamedStoredProcedureQueries(_cls, ((NamedStoredProcedureQuery) anno)); + break; case SEQ_GENERATOR: if (isMappingOverrideMode()) parseSequenceGenerator(_cls, (SequenceGenerator) anno); @@ -1043,8 +1068,8 @@ public class AnnotationPersistenceMetaDa * If FetchGroup A includes FetchGroup B, then a bi-link is set between * A and B. Both A and B must be declared in the same Class. * <br> - * Call {@link #parseFetchAttribute(ClassMetaData, - * org.apache.openjpa.meta.FetchGroup, FetchAttribute)} only after the + * Call {@link #parseFetchAttribute(ClassMetaData, org.apache.openjpa.meta.FetchGroup, FetchAttributeImpl)} + * only after the * bi-links have been established, because a field f will not only add the * fetch group A which explicitly includes f to its custom fetch groups but * also will also add any fetch group B that includes A. @@ -2128,5 +2153,75 @@ public class AnnotationPersistenceMetaDa protected String normalizeCatalogName(String catName) { return catName; } + + + protected MultiQueryMetaData.Parameter.Mode toKernelParameterMode(ParameterMode mode) { + switch (mode) { + case IN : return MultiQueryMetaData.Parameter.Mode.IN; + case OUT: return MultiQueryMetaData.Parameter.Mode.OUT; + case INOUT: return MultiQueryMetaData.Parameter.Mode.INOUT; + case REF_CURSOR: return MultiQueryMetaData.Parameter.Mode.CURSOR; + default : return MultiQueryMetaData.Parameter.Mode.IN; + } + } + + protected void addSourceInfo(AnnotatedElement el, QueryMetaData meta) { + meta.setSource(getSourceFile(), (el instanceof Class) ? el : null, + SourceTracker.SRC_ANNOTATIONS, getSourceFile() == null ? "" : getSourceFile().getPath()); + if (isMetaDataMode()) + meta.setSourceMode(MODE_META); + else if (isMappingMode()) + meta.setSourceMode(MODE_MAPPING); + else + meta.setSourceMode(MODE_QUERY); + } + + protected void addHints(QueryMetaData meta, QueryHint...hints) { + for (QueryHint hint : hints) + meta.addHint(hint.name(), hint.value()); + + } + + private void parseNamedStoredProcedureQueries(AnnotatedElement el, NamedStoredProcedureQuery... procs) { + for (NamedStoredProcedureQuery proc : procs) { + if (StringUtils.isEmpty(proc.name())) + throw new MetaDataException(_loc.get("stored-proc-no-name", el)); + if (StringUtils.isEmpty(proc.procedureName())) + throw new MetaDataException(_loc.get("stored-proc-no-dbname", el)); + + // Query metadata name + MultiQueryMetaData meta = new MultiQueryMetaData(_cls, proc.name(), proc.procedureName(), false); + QueryMetaData existing = getRepository().addQueryMetaData(meta); + if (existing != null && existing.getDefiningType() != meta.getDefiningType()) { + getLog().warn(_loc.get("dup-query", meta.getName(), el, existing.getDefiningType())); + } + + // Important: The query string is the name of the database stored procedure + meta.setQueryString(proc.procedureName()); + + // For each mapping name/result class, add a component metadata + // The spec restricts that either ResultMappingName or ResultClasses be specified, but not both. + // This is relevant because the order of mapping must match the order in which the + // components are returned + Class<?>[] resultClasses = proc.resultClasses(); + String[] resultSetMappings = proc.resultSetMappings(); + if (resultClasses.length > 0 && resultSetMappings.length > 0) + throw new MetaDataException(_loc.get("stored-proc-both-mapping", el)); + for (Class<?> res : resultClasses) { + meta.addComponent(res); + } + for (String mapping : resultSetMappings) { + meta.addComponent(mapping); + } + StoredProcedureParameter[] params = proc.parameters(); + for (StoredProcedureParameter param : params) { + MultiQueryMetaData.Parameter p = new MultiQueryMetaData.Parameter( + param.name(), param.type(), toKernelParameterMode(param.mode())); + meta.registerParameter(p); + } + addHints(meta, proc.hints()); + addSourceInfo(el, meta); + } + } }
Modified: openjpa/branches/openjpa_jpa-2.1/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/EntityManagerFactoryImpl.java URL: http://svn.apache.org/viewvc/openjpa/branches/openjpa_jpa-2.1/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/EntityManagerFactoryImpl.java?rev=1683972&r1=1683971&r2=1683972&view=diff ============================================================================== --- openjpa/branches/openjpa_jpa-2.1/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/EntityManagerFactoryImpl.java (original) +++ openjpa/branches/openjpa_jpa-2.1/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/EntityManagerFactoryImpl.java Sun Jun 7 01:05:22 2015 @@ -42,6 +42,7 @@ import org.apache.openjpa.lib.log.Log; import org.apache.openjpa.lib.util.Closeable; import org.apache.openjpa.lib.util.Localizer; import org.apache.openjpa.meta.MetaDataRepository; +import org.apache.openjpa.meta.QueryMetaData; import org.apache.openjpa.persistence.criteria.CriteriaBuilderImpl; import org.apache.openjpa.persistence.criteria.OpenJPACriteriaBuilder; import org.apache.openjpa.persistence.meta.MetamodelImpl; @@ -364,7 +365,11 @@ public class EntityManagerFactoryImpl @Override public void addNamedQuery(String name, Query query) { - throw new UnsupportedOperationException("JPA 2.1"); + org.apache.openjpa.kernel.Query kernelQuery = ((QueryImpl<?>)query).getDelegate(); + MetaDataRepository metaDataRepositoryInstance = _factory.getConfiguration().getMetaDataRepositoryInstance(); + QueryMetaData metaData = metaDataRepositoryInstance.newQueryMetaData(null, null); + metaData.setFrom(kernelQuery); + metaDataRepositoryInstance.addQueryMetaData(metaData); } @Override Modified: openjpa/branches/openjpa_jpa-2.1/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/EntityManagerImpl.java URL: http://svn.apache.org/viewvc/openjpa/branches/openjpa_jpa-2.1/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/EntityManagerImpl.java?rev=1683972&r1=1683971&r2=1683972&view=diff ============================================================================== --- openjpa/branches/openjpa_jpa-2.1/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/EntityManagerImpl.java (original) +++ openjpa/branches/openjpa_jpa-2.1/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/EntityManagerImpl.java Sun Jun 7 01:05:22 2015 @@ -83,6 +83,8 @@ import org.apache.openjpa.lib.util.Close import org.apache.openjpa.lib.util.Localizer; import org.apache.openjpa.meta.ClassMetaData; import org.apache.openjpa.meta.FieldMetaData; +import org.apache.openjpa.meta.MetaDataRepository; +import org.apache.openjpa.meta.MultiQueryMetaData; import org.apache.openjpa.meta.QueryMetaData; import org.apache.openjpa.meta.SequenceMetaData; import org.apache.openjpa.persistence.criteria.CriteriaBuilderImpl; @@ -119,7 +121,8 @@ public class EntityManagerImpl private Map<FetchConfiguration,FetchPlan> _plans = new IdentityHashMap<FetchConfiguration,FetchPlan>(1); protected RuntimeExceptionTranslator _ret = PersistenceExceptions.getRollbackTranslator(this); private boolean _convertPositionalParams = false; - + private boolean _isJoinedToTransaction; + public EntityManagerImpl() { // for Externalizable } @@ -559,6 +562,13 @@ public class EntityManagerImpl } public void joinTransaction() { + if (!_broker.syncWithManagedTransaction()) { + throw new TransactionRequiredException(_loc.get + ("no-managed-trans"), null, null, false); + } else { + _isJoinedToTransaction = true; + } + assertNotCloseInvoked(); if (!_broker.syncWithManagedTransaction()) throw new TransactionRequiredException(_loc.get @@ -567,8 +577,7 @@ public class EntityManagerImpl @Override public boolean isJoinedToTransaction() { - // throw new UnsupportedOperationException("JPA 2.1"); - return false; + return isActive() && _isJoinedToTransaction; } public void begin() { @@ -1079,22 +1088,60 @@ public class EntityManagerImpl @Override public StoredProcedureQuery createNamedStoredProcedureQuery(String name) { - throw new UnsupportedOperationException("JPA 2.1"); + QueryMetaData meta = getQueryMetadata(name); + if (!MultiQueryMetaData.class.isInstance(meta)) { + throw new RuntimeException(name + " is not an identifier for a Stored Procedure Query"); + } + return newProcedure(((MultiQueryMetaData)meta).getProcedureName(), (MultiQueryMetaData)meta); } @Override public StoredProcedureQuery createStoredProcedureQuery(String procedureName) { - throw new UnsupportedOperationException("JPA 2.1"); + return newProcedure(procedureName, null); } @Override public StoredProcedureQuery createStoredProcedureQuery(String procedureName, Class... resultClasses) { - throw new UnsupportedOperationException("JPA 2.1"); + String tempName = "StoredProcedure-"+System.nanoTime(); + MultiQueryMetaData meta = new MultiQueryMetaData(null, tempName, procedureName, true); + for (Class<?> res : resultClasses) { + meta.addComponent(res); + } + return newProcedure(procedureName, meta); } @Override public StoredProcedureQuery createStoredProcedureQuery(String procedureName, String... resultSetMappings) { - throw new UnsupportedOperationException("JPA 2.1"); + String tempName = "StoredProcedure-"+System.nanoTime(); + MultiQueryMetaData meta = new MultiQueryMetaData(null, tempName, procedureName, true); + for (String mapping : resultSetMappings) { + meta.addComponent(mapping); + } + return newProcedure(procedureName, meta); + } + + /** + * Creates a query to execute a Stored Procedure. + * <br> + * Construction of a {@link StoredProcedureQuery} object is a three step process + * <LI> + * <LI>a {@link org.apache.openjpa.kernel.Query kernel query} {@code kQ} is created for + * {@link QueryLanguages#LANG_SQL SQL} language with the string {@code S} + * <LI>a {@link QueryImpl facade query} {@code fQ} is created that delegates to the kernel query {@code kQ} + * <LI>a {@link StoredProcedureQueryImpl stored procedure query} is created that delegates to the facade query + * {@code fQ}. + * <br> + * + */ + private StoredProcedureQuery newProcedure(String procedureName, MultiQueryMetaData meta) { + org.apache.openjpa.kernel.QueryImpl kernelQuery = (org.apache.openjpa.kernel.QueryImpl) + _broker.newQuery(QueryLanguages.LANG_STORED_PROC, procedureName); + kernelQuery.getStoreQuery().setQuery(meta); + if (meta != null) { + getConfiguration().getMetaDataRepositoryInstance().addQueryMetaData(meta); + kernelQuery.setResultMapping(null, meta.getResultSetMappingName()); + } + return new StoredProcedureQueryImpl(procedureName, meta, new QueryImpl(this, _ret, kernelQuery, meta)); } protected <T> QueryImpl<T> newQueryImpl(org.apache.openjpa.kernel.Query kernelQuery, QueryMetaData qmd) { @@ -1942,4 +1989,13 @@ public class EntityManagerImpl } return properties; } + + private QueryMetaData getQueryMetadata(String name) { + MetaDataRepository repos = _broker.getConfiguration().getMetaDataRepositoryInstance(); + QueryMetaData meta = repos.getQueryMetaData(null, name, _broker.getClassLoader(), true); + if (meta == null) { + throw new RuntimeException("No query named [" + name + "]"); + } + return meta; + } } Modified: openjpa/branches/openjpa_jpa-2.1/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/MetaDataTag.java URL: http://svn.apache.org/viewvc/openjpa/branches/openjpa_jpa-2.1/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/MetaDataTag.java?rev=1683972&r1=1683971&r2=1683972&view=diff ============================================================================== --- openjpa/branches/openjpa_jpa-2.1/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/MetaDataTag.java (original) +++ openjpa/branches/openjpa_jpa-2.1/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/MetaDataTag.java Sun Jun 7 01:05:22 2015 @@ -88,5 +88,8 @@ public enum MetaDataTag { READ_ONLY, TYPE, REPLICATED, - OPENJPA_VERSION + OPENJPA_VERSION, + // JPA 2.1 + STOREDPROCEDURE_QUERIES, + STOREDPROCEDURE_QUERY } Modified: openjpa/branches/openjpa_jpa-2.1/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/PersistenceMetaDataFactory.java URL: http://svn.apache.org/viewvc/openjpa/branches/openjpa_jpa-2.1/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/PersistenceMetaDataFactory.java?rev=1683972&r1=1683971&r2=1683972&view=diff ============================================================================== --- openjpa/branches/openjpa_jpa-2.1/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/PersistenceMetaDataFactory.java (original) +++ openjpa/branches/openjpa_jpa-2.1/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/PersistenceMetaDataFactory.java Sun Jun 7 01:05:22 2015 @@ -20,6 +20,7 @@ package org.apache.openjpa.persistence; import java.io.File; import java.io.IOException; +import java.lang.annotation.Annotation; import java.net.URL; import java.security.AccessController; import java.util.ArrayList; @@ -39,6 +40,8 @@ import javax.persistence.NamedNativeQuer import javax.persistence.NamedNativeQuery; import javax.persistence.NamedQueries; import javax.persistence.NamedQuery; +import javax.persistence.NamedStoredProcedureQueries; +import javax.persistence.NamedStoredProcedureQuery; import javax.persistence.SqlResultSetMapping; import javax.persistence.SqlResultSetMappings; import javax.persistence.metamodel.StaticMetamodel; @@ -371,10 +374,20 @@ public class PersistenceMetaDataFactory hasNamedNativeQuery(queryName, ((NamedNativeQueries) cls. getAnnotation(NamedNativeQueries.class)).value())) return cls; + if (isAnnotated(cls, NamedStoredProcedureQuery.class) + && hasNamedStoredProcedure(queryName, cls.getAnnotation(NamedStoredProcedureQuery.class))) + return cls; + if (isAnnotated(cls, NamedStoredProcedureQueries.class) + && hasNamedStoredProcedure(queryName, cls.getAnnotation(NamedStoredProcedureQueries.class).value())) + return cls; } return null; } + private boolean isAnnotated(Class<?> cls, Class<? extends Annotation> annotationClazz) { + return AccessController.doPrivileged(J2DoPrivHelper.isAnnotationPresentAction(cls, annotationClazz)); + } + @Override public Class<?> getResultSetMappingScope(String rsMappingName, ClassLoader loader) { @@ -416,6 +429,14 @@ public class PersistenceMetaDataFactory return true; } return false; + } + + private boolean hasNamedStoredProcedure(String query, NamedStoredProcedureQuery... queries) { + for (NamedStoredProcedureQuery q : queries) { + if (query.equals(q.name())) + return true; + } + return false; } private boolean hasNamedNativeQuery(String query, Added: openjpa/branches/openjpa_jpa-2.1/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/StoredProcedureQueryImpl.java URL: http://svn.apache.org/viewvc/openjpa/branches/openjpa_jpa-2.1/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/StoredProcedureQueryImpl.java?rev=1683972&view=auto ============================================================================== --- openjpa/branches/openjpa_jpa-2.1/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/StoredProcedureQueryImpl.java (added) +++ openjpa/branches/openjpa_jpa-2.1/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/StoredProcedureQueryImpl.java Sun Jun 7 01:05:22 2015 @@ -0,0 +1,415 @@ +/* + * 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 org.apache.openjpa.kernel.DelegatingResultList; +import org.apache.openjpa.kernel.QueryResultCallback; +import org.apache.openjpa.lib.rop.ResultList; +import org.apache.openjpa.lib.rop.ResultObjectProvider; +import org.apache.openjpa.lib.util.Localizer; +import org.apache.openjpa.meta.MultiQueryMetaData; +import org.apache.openjpa.util.RuntimeExceptionTranslator; +import org.apache.openjpa.util.UserException; + +import java.util.Calendar; +import java.util.Date; +import java.util.List; +import java.util.Map; +import java.util.Set; +import javax.persistence.*; +import javax.persistence.NoResultException; +import javax.persistence.NonUniqueResultException; + +/** + * Implements Store Procedure based query for JPA facade. + * <br> + * A {@link StoredProcedureQuery stored procedure query} differs from other query types because it may return + * more than one result set, apart from an optional update count, whereas the traditional query processing in OpenJPA + * via the abstractions of {@link ResultObjectProvider} and {@link org.apache.openjpa.jdbc.sql.Result} + * assumed that a query will return its + * result in a single list. + * <br> + * This query resorts to a callback mechanism, where the execution of the query returns not a result, but a + * {@link QueryResultCallback callback object} that can be used to callback to OpenJPA kernel to get a series of + * results via the traditional result processing pathway. + * + * @author Pinaki Poddar + * @author Romain Manni-Bucau + */ +// TODO: add lock +public class StoredProcedureQueryImpl implements StoredProcedureQuery { + private static final Localizer _loc = Localizer.forPackage(QueryImpl.class); + + private final String _name; + private final QueryImpl<?> _delegate; + private final MultiQueryMetaData _meta; + private QueryResultCallback _callback; + private boolean _declaredParams; // mainly a flag for now (null or not) + + /** + * Construct a query for executing a Stored Procedure. + * @param procedureName name of the database stored procedure. + * @param meta + * @param delegate the delegate which manages bind parameters on behalf of this + */ + public StoredProcedureQueryImpl(String procedureName, MultiQueryMetaData meta, QueryImpl<?> delegate) { + _name = procedureName; + if (!isValidProcedureName(procedureName)) { + throw new RuntimeException(procedureName + " is not a valid procedure name"); + } + _meta = meta; + _delegate = delegate; + _delegate.compile(); + } + + /** + * Gets the facade delegate that manages bind parameters on behalf of this receiver. + * + * @return + */ + public OpenJPAQuery<?> getDelegate() { + return _delegate; + } + + /** + * Gets the kernel delegate that is handles actual execution on behalf of this receiver. + * + * @return + */ + public org.apache.openjpa.kernel.Query getExecutableQuery() { + return _delegate.getDelegate(); + } + + private void buildParametersIfNeeded() { + if (!_declaredParams) { + for (MultiQueryMetaData.Parameter entry : _meta.getParameters()) { + final Object key; + final Parameter<?> param; + if (entry.getName() == null) { + key = entry.getPosition(); + param = new ParameterImpl(entry.getPosition(), entry.getType()); + } else { + key = entry.getName(); + param = new ParameterImpl(entry.getName(), entry.getType()); + } + _delegate.declareParameter(key, param); + } + _declaredParams = true; + } + } + + /** + * Executes this receiver by delegation to the underlying executable query. + * <br> + * This method is multi-call safe. The underlying executable query is executed + * <em>only</em> for the first invocation. Subsequent + */ + @Override + public boolean execute() { + if (_callback == null) { + _callback = (QueryResultCallback) getExecutableQuery().execute(_delegate.getParameterValues()); + } + return _callback.getExecutionResult(); + } + + @Override + public List getResultList() { + execute(); + try { + Object list = _callback.callback(); + RuntimeExceptionTranslator trans = PersistenceExceptions + .getRollbackTranslator(_delegate.getEntityManager()); + return new DelegatingResultList((ResultList) list, trans); + } catch (Exception ex) { + throw new javax.persistence.PersistenceException(ex); + } + } + + @Override + public Object getSingleResult() { + execute(); + try { + ResultList result = (ResultList) _callback.callback(); + if (result == null || result.isEmpty()) + throw new NoResultException(_loc.get("no-result", _name) + .getMessage()); + if (result.size() > 1) + throw new NonUniqueResultException(_loc.get("non-unique-result", + _name, result.size()).getMessage()); + RuntimeExceptionTranslator trans = PersistenceExceptions + .getRollbackTranslator(_delegate.getEntityManager()); + return new DelegatingResultList(result, trans).iterator().next(); + } catch (Exception ex) { + throw new javax.persistence.PersistenceException(ex); + } + } + + @Override + public boolean hasMoreResults() { + return _callback != null && _callback.hasMoreResults(); + } + + @Override + public int getUpdateCount() { + assertExecuted(); + return _callback.getUpdateCount(); + } + + @Override + public int executeUpdate() { + execute(); + return _callback.getUpdateCount(); + } + + @Override + public <T> Parameter<T> getParameter(String name, Class<T> type) { + // TODO JPA 2.1 Method + return _delegate.getParameter(name, type); + } + + @Override + public <T> Parameter<T> getParameter(int position, Class<T> type) { + // TODO JPA 2.1 Method + return _delegate.getParameter(position, type); + } + + @Override + public boolean isBound(Parameter<?> param) { + // TODO JPA 2.1 Method + return _delegate.isBound(param); + } + + @Override + public <T> T getParameterValue(Parameter<T> param) { + // TODO JPA 2.1 Method + return _delegate.getParameterValue(param); + } + + @Override + public <T> T unwrap(Class<T> cls) { + // TODO JPA 2.1 Method + return _delegate.unwrap(cls); + } + + @Override + public <T> StoredProcedureQuery setParameter(Parameter<T> param, T value) { + buildParametersIfNeeded(); + _delegate.setParameter(param, value); + return this; + } + + @Override + public StoredProcedureQuery setParameter(Parameter<Calendar> param, Calendar cal, TemporalType temporalType) { + buildParametersIfNeeded(); + _delegate.setParameter(param, cal, temporalType); + return this; + } + + @Override + public StoredProcedureQuery setParameter(Parameter<Date> param, Date value, TemporalType temporalType) { + buildParametersIfNeeded(); + _delegate.setParameter(param, value, temporalType); + return this; + } + + @Override + public StoredProcedureQuery registerStoredProcedureParameter(int position, Class type, ParameterMode mode) { + buildParametersIfNeeded(); + ParameterImpl param = new ParameterImpl(position, type); + _delegate.declareParameter(position, param); + return this; + } + + @Override + public StoredProcedureQuery registerStoredProcedureParameter(String name, Class type, ParameterMode mode) { + buildParametersIfNeeded(); + ParameterImpl param = new ParameterImpl(name, type); + _delegate.declareParameter(name, param); + return this; + } + + @Override + public Object getOutputParameterValue(int position) { + return _callback == null ? null : _callback.getOut(position); + } + + @Override + public Object getOutputParameterValue(String parameterName) { + return _callback == null ? null : _callback.getOut(parameterName); + } + + @Override + public javax.persistence.Query setMaxResults(int maxResult) { + // TODO JPA 2.1 Method + return _delegate.setMaxResults(maxResult); + } + + @Override + public int getMaxResults() { + // TODO JPA 2.1 Method + return _delegate.getMaxResults(); + } + + @Override + public javax.persistence.Query setFirstResult(int startPosition) { + // TODO JPA 2.1 Method + return _delegate.setFirstResult(startPosition); + } + + @Override + public int getFirstResult() { + // TODO JPA 2.1 Method + return _delegate.getFirstResult(); + } + + @Override + public Map<String, Object> getHints() { + // TODO JPA 2.1 Method + return _delegate.getHints(); + } + + @Override + public Set<Parameter<?>> getParameters() { + buildParametersIfNeeded(); + return _delegate.getParameters(); + } + + @Override + public Parameter<?> getParameter(String name) { + buildParametersIfNeeded(); + return _delegate.getParameter(name); + } + + @Override + public Parameter<?> getParameter(int position) { + buildParametersIfNeeded(); + return _delegate.getParameter(position); + } + + @Override + public Object getParameterValue(String name) { + buildParametersIfNeeded(); + return _delegate.getParameterValue(name); + } + + @Override + public Object getParameterValue(int position) { + buildParametersIfNeeded(); + return _delegate.getParameter(position); + } + + @Override + public FlushModeType getFlushMode() { + // TODO JPA 2.1 Method + return _delegate.getFlushMode(); + } + + @Override + public javax.persistence.Query setLockMode(LockModeType lockMode) { + // TODO JPA 2.1 Method + return _delegate.setLockMode(lockMode); + } + + @Override + public LockModeType getLockMode() { + // TODO JPA 2.1 Method + return _delegate.getLockMode(); + } + + @Override + public StoredProcedureQuery setHint(String hintName, Object value) { + _delegate.setHint(hintName, value); + return this; + } + + @Override + public StoredProcedureQuery setParameter(String name, Object value) { + buildParametersIfNeeded(); + _delegate.setParameter(name, value); + return this; + } + + @Override + public StoredProcedureQuery setParameter(String name, Calendar cal, TemporalType temporalType) { + buildParametersIfNeeded(); + _delegate.setParameter(name, cal, temporalType); + return this; + } + + @Override + public StoredProcedureQuery setParameter(String name, Date date, TemporalType temporalType) { + buildParametersIfNeeded(); + _delegate.setParameter(name, date, temporalType); + return this; + } + + @Override + public StoredProcedureQuery setParameter(int position, Object value) { + buildParametersIfNeeded(); + _delegate.setParameter(position, value); + return this; + } + + @Override + public StoredProcedureQuery setParameter(int position, Calendar value, TemporalType temporalType) { + buildParametersIfNeeded(); + _delegate.setParameter(position, value, temporalType); + return this; + } + + @Override + public StoredProcedureQuery setParameter(int position, Date value, TemporalType temporalType) { + buildParametersIfNeeded(); + _delegate.setParameter(position, value, temporalType); + return this; + } + + @Override + public StoredProcedureQuery setFlushMode(FlushModeType flushMode) { + // TODO JPA 2.1 Method + _delegate.setFlushMode(flushMode); + return this; + } + + /** + * Asserts that user has executed this query. + */ + void assertExecuted() { + if (_callback == null) { + throw new UserException(this + " has not been executed"); + } + } + + boolean isValidProcedureName(String s) { + if (s == null || s.trim().length() == 0) { + return false; + } + for (int i = 0; i < s.length(); i++) { + char ch = s.charAt(i); + if (ch == '#' || ch == '$' || Character.isJavaIdentifierPart(ch)) + continue; + return false; + } + return true; + } + + public String toString() { + return _name; + } +} Modified: openjpa/branches/openjpa_jpa-2.1/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/XMLPersistenceMetaDataParser.java URL: http://svn.apache.org/viewvc/openjpa/branches/openjpa_jpa-2.1/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/XMLPersistenceMetaDataParser.java?rev=1683972&r1=1683971&r2=1683972&view=diff ============================================================================== --- openjpa/branches/openjpa_jpa-2.1/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/XMLPersistenceMetaDataParser.java (original) +++ openjpa/branches/openjpa_jpa-2.1/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/XMLPersistenceMetaDataParser.java Sun Jun 7 01:05:22 2015 @@ -601,7 +601,7 @@ public class XMLPersistenceMetaDataParse @Override protected boolean startSystemElement(String name, Attributes attrs) throws SAXException { - Object tag = (Object) _elems.get(name); + Object tag = _elems.get(name); boolean ret = false; if (tag == null) { if (isMappingOverrideMode())