You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@openjpa.apache.org by rm...@apache.org on 2015/06/07 03:05:23 UTC
svn commit: r1683972 [1/2] - in /openjpa/branches/openjpa_jpa-2.1:
openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/identifier/
openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/
openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/meta/ openjp...
Author: rmannibucau
Date: Sun Jun 7 01:05:22 2015
New Revision: 1683972
URL: http://svn.apache.org/r1683972
Log:
OPENJPA-2592 basic stored procedure impl import
Added:
openjpa/branches/openjpa_jpa-2.1/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/StoredProcedureQuery.java
openjpa/branches/openjpa_jpa-2.1/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/XROP.java
openjpa/branches/openjpa_jpa-2.1/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/sql/StoredProcedure.java
openjpa/branches/openjpa_jpa-2.1/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/QueryResultCallback.java
openjpa/branches/openjpa_jpa-2.1/openjpa-kernel/src/main/java/org/apache/openjpa/meta/MultiQueryMetaData.java
openjpa/branches/openjpa_jpa-2.1/openjpa-lib/src/main/java/org/apache/openjpa/lib/rop/BatchedResultObjectProvider.java
openjpa/branches/openjpa_jpa-2.1/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/jdbc/procedure/
openjpa/branches/openjpa_jpa-2.1/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/jdbc/procedure/TestStoredProcedure.java
openjpa/branches/openjpa_jpa-2.1/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/jdbc/procedure/derby/
openjpa/branches/openjpa_jpa-2.1/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/jdbc/procedure/derby/Procedures.java
openjpa/branches/openjpa_jpa-2.1/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/jdbc/procedure/entity/
openjpa/branches/openjpa_jpa-2.1/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/jdbc/procedure/entity/EntityWithStoredProcedure.java
openjpa/branches/openjpa_jpa-2.1/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/StoredProcedureQueryImpl.java
Modified:
openjpa/branches/openjpa_jpa-2.1/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/identifier/DBIdentifier.java
openjpa/branches/openjpa_jpa-2.1/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/JDBCStoreManager.java
openjpa/branches/openjpa_jpa-2.1/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/meta/MappingRepository.java
openjpa/branches/openjpa_jpa-2.1/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/meta/QueryResultMapping.java
openjpa/branches/openjpa_jpa-2.1/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/schema/Column.java
openjpa/branches/openjpa_jpa-2.1/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/sql/DBDictionary.java
openjpa/branches/openjpa_jpa-2.1/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/sql/ResultSetResult.java
openjpa/branches/openjpa_jpa-2.1/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/QueryImpl.java
openjpa/branches/openjpa_jpa-2.1/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/QueryLanguages.java
openjpa/branches/openjpa_jpa-2.1/openjpa-kernel/src/main/java/org/apache/openjpa/meta/MetaDataRepository.java
openjpa/branches/openjpa_jpa-2.1/openjpa-persistence-jdbc/src/main/java/org/apache/openjpa/persistence/jdbc/AnnotationPersistenceMappingParser.java
openjpa/branches/openjpa_jpa-2.1/openjpa-persistence-jdbc/src/main/java/org/apache/openjpa/persistence/jdbc/MappingTag.java
openjpa/branches/openjpa_jpa-2.1/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/test/AbstractPersistenceTestCase.java
openjpa/branches/openjpa_jpa-2.1/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/AbstractQuery.java
openjpa/branches/openjpa_jpa-2.1/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/AnnotationPersistenceMetaDataParser.java
openjpa/branches/openjpa_jpa-2.1/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/EntityManagerFactoryImpl.java
openjpa/branches/openjpa_jpa-2.1/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/EntityManagerImpl.java
openjpa/branches/openjpa_jpa-2.1/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/MetaDataTag.java
openjpa/branches/openjpa_jpa-2.1/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/PersistenceMetaDataFactory.java
openjpa/branches/openjpa_jpa-2.1/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/XMLPersistenceMetaDataParser.java
Modified: openjpa/branches/openjpa_jpa-2.1/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/identifier/DBIdentifier.java
URL: http://svn.apache.org/viewvc/openjpa/branches/openjpa_jpa-2.1/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/identifier/DBIdentifier.java?rev=1683972&r1=1683971&r2=1683972&view=diff
==============================================================================
--- openjpa/branches/openjpa_jpa-2.1/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/identifier/DBIdentifier.java (original)
+++ openjpa/branches/openjpa_jpa-2.1/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/identifier/DBIdentifier.java Sun Jun 7 01:05:22 2015
@@ -46,6 +46,7 @@ public class DBIdentifier extends Identi
INDEX,
FOREIGN_KEY,
CONSTANT,
+ PROCEDURE,
NULL
}
@@ -603,6 +604,10 @@ public class DBIdentifier extends Identi
return newIdentifier(name,id, toUpper, delimit, false);
}
+ public static DBIdentifier newProcedure(String name) {
+ return newIdentifier(name, DBIdentifierType.PROCEDURE);
+ }
+
/**
* Constructs a new identifier (potentially a compound QualifiedDBIdentifier) with the provided
* name an type. Optionally, converting the name to upper case and delimiting it.
Modified: openjpa/branches/openjpa_jpa-2.1/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/JDBCStoreManager.java
URL: http://svn.apache.org/viewvc/openjpa/branches/openjpa_jpa-2.1/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/JDBCStoreManager.java?rev=1683972&r1=1683971&r2=1683972&view=diff
==============================================================================
--- openjpa/branches/openjpa_jpa-2.1/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/JDBCStoreManager.java (original)
+++ openjpa/branches/openjpa_jpa-2.1/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/JDBCStoreManager.java Sun Jun 7 01:05:22 2015
@@ -910,6 +910,9 @@ public class JDBCStoreManager implements
if (QueryLanguages.LANG_PREPARED_SQL.equals(language)) {
return new PreparedSQLStoreQuery(this);
}
+ if (QueryLanguages.LANG_STORED_PROC.equals(language)) {
+ return new StoredProcedureQuery(this);
+ }
return null;
}
Added: openjpa/branches/openjpa_jpa-2.1/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/StoredProcedureQuery.java
URL: http://svn.apache.org/viewvc/openjpa/branches/openjpa_jpa-2.1/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/StoredProcedureQuery.java?rev=1683972&view=auto
==============================================================================
--- openjpa/branches/openjpa_jpa-2.1/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/StoredProcedureQuery.java (added)
+++ openjpa/branches/openjpa_jpa-2.1/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/StoredProcedureQuery.java Sun Jun 7 01:05:22 2015
@@ -0,0 +1,212 @@
+/*
+ * 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.jdbc.kernel;
+
+import org.apache.openjpa.jdbc.meta.MappingRepository;
+import org.apache.openjpa.jdbc.meta.QueryResultMapping;
+import org.apache.openjpa.jdbc.schema.Column;
+import org.apache.openjpa.jdbc.sql.DBDictionary;
+import org.apache.openjpa.jdbc.sql.StoredProcedure;
+import org.apache.openjpa.kernel.AbstractStoreQuery;
+import org.apache.openjpa.kernel.QueryContext;
+import org.apache.openjpa.kernel.QueryOperations;
+import org.apache.openjpa.kernel.StoreQuery;
+import org.apache.openjpa.lib.rop.ResultObjectProvider;
+import org.apache.openjpa.meta.ClassMetaData;
+import org.apache.openjpa.meta.MultiQueryMetaData;
+import org.apache.openjpa.meta.QueryMetaData;
+import org.apache.openjpa.util.InternalException;
+
+import java.sql.CallableStatement;
+import java.sql.Connection;
+import java.sql.SQLException;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.List;
+import java.util.Map;
+
+import static java.util.Arrays.asList;
+
+/**
+ * Executes a stored procedure.
+ *
+ * @author ppoddar
+ *
+ */
+@SuppressWarnings("serial")
+public class StoredProcedureQuery extends AbstractStoreQuery {
+ private static final Object[] NO_PARAM = new Object[0];
+
+ JDBCStore _store;
+ StoredProcedure _proc;
+ private MultiQueryMetaData _meta;
+
+ public StoredProcedureQuery(JDBCStore store) {
+ _store = store;
+ }
+
+ public int getOperation() {
+ return QueryOperations.OP_SELECT;
+ }
+
+ public StoredProcedure getProcedure() {
+ return _proc;
+ }
+
+ public DBDictionary getDictionary() {
+ return _store.getDBDictionary();
+ }
+
+ @Override
+ public boolean setQuery(Object meta) {
+ if (meta == null || meta instanceof MultiQueryMetaData) {
+ _meta = (MultiQueryMetaData)meta;
+ return true;
+ } else {
+ throw new InternalException("Unknown " + meta);
+ }
+ }
+
+ public Executor newDataStoreExecutor(ClassMetaData meta, boolean subclasses) {
+ List<QueryResultMapping> mappings = null;
+ List<Class<?>> classes = null;
+ if (_meta != null) {
+ List<QueryMetaData> parts = _meta.getComponents();
+ if (parts != null && !parts.isEmpty()) {
+ mappings = new ArrayList<QueryResultMapping>();
+ classes = new ArrayList<Class<?>>();
+ MappingRepository repos = _store.getConfiguration().getMappingRepositoryInstance();
+ for (QueryMetaData part : parts) {
+ QueryResultMapping mapping = repos.getQueryResultMapping(ctx.getResultMappingScope(),
+ part.getResultSetMappingName(),
+ null, true);
+ if (mapping != null) {
+ mappings.add(mapping);
+ }
+ if (part.getResultType() != null) {
+ classes.add(part.getResultType());
+ }
+ }
+ }
+ }
+ return new StoredProcedureQueryExecutor(this, mappings, classes);
+ }
+
+ public boolean supportsParameterDeclarations() {
+ return false;
+ }
+
+ public boolean supportsDataStoreExecution() {
+ return true;
+ }
+
+ public boolean requiresCandidateType() {
+ return false;
+ }
+
+ public boolean requiresParameterDeclarations() {
+ return false;
+ }
+
+
+ public class StoredProcedureQueryExecutor extends AbstractExecutor {
+ private final List<Class<?>> _resultClasses;
+ private final List<QueryResultMapping> _resultMappings;
+
+ public StoredProcedureQueryExecutor(StoredProcedureQuery q, List<QueryResultMapping> resultMapping,
+ List<Class<?>> classes) {
+ QueryContext ctx = q.getContext();
+ _resultMappings = resultMapping;
+ _resultClasses = classes;
+ // Look for the named Stored Procedure in the database
+ String procName = ctx.getQueryString();
+ _proc = getStoredProcedure(_store.getConnection(), _store.getDBDictionary(), procName);
+ if (_proc == null) {
+ throw new RuntimeException("Can not find stored procedure " + procName);
+ }
+ }
+
+ StoredProcedure getStoredProcedure(Connection conn, DBDictionary dict, String procedureName) {
+ try {
+ StoredProcedure sp = dict.getStoredProcedure(conn.getMetaData(), null, null, procedureName);
+ if (sp != null) {
+ return sp;
+ }
+ } catch (SQLException ex) {
+ throw new RuntimeException(ex);
+ } finally {
+ try {
+ conn.close();
+ } catch (SQLException ex) {
+
+ }
+ }
+ throw new RuntimeException("Procedure [" + procedureName + "] not found");
+ }
+
+ @Override
+ public ResultObjectProvider executeQuery(StoreQuery q, Object[] params, Range range) {
+ try {
+ DBDictionary dict = _store.getDBDictionary();
+ Connection conn = _store.getConnection();
+ CallableStatement stmnt = conn.prepareCall(_proc.getCallSQL());
+
+ final StoredProcedureQuery spq = StoredProcedureQuery.class.cast(q);
+ for (Column c : spq.getProcedure().getInColumns()) {
+ dict.setUnknown(stmnt, c.getIndex() + 1, params[c.getIndex()], c);
+ }
+ for (Column c : spq.getProcedure().getInOutColumns()) {
+ final int index = c.getIndex() + 1;
+ stmnt.registerOutParameter(index, c.getType());
+ dict.setUnknown(stmnt, index, params[index - 1], c);
+ }
+ for (Column c : spq.getProcedure().getOutColumns()) {
+ stmnt.registerOutParameter(c.getIndex() + 1, c.getType());
+ }
+
+ JDBCFetchConfiguration fetch = (JDBCFetchConfiguration)q.getContext().getFetchConfiguration();
+ ResultObjectProvider rop = new XROP(_resultMappings, _resultClasses, _store, fetch, stmnt);
+ rop.open();
+ return rop;
+ } catch (Exception e) {
+ throw new RuntimeException(e);
+ }
+ }
+
+ @Override
+ public Object[] toParameterArray(StoreQuery q, Map<?, ?> userParams) {
+ if (userParams == null) return NO_PARAM;
+ Object[] array = new Object[userParams.size()];
+ int i = 0;
+ StoredProcedureQuery storedProcedureQuery = StoredProcedureQuery.class.cast(q);
+ for (final Column[] columns : asList(
+ storedProcedureQuery.getProcedure().getInColumns(),
+ storedProcedureQuery.getProcedure().getInOutColumns())) {
+ for (Column c : columns) {
+ array[i] = userParams.get(c.getIdentifier().getName());
+ if (array[i++] == null) {
+ userParams.get(c.getIndex());
+ }
+ }
+ }
+ return array;
+ }
+
+ }
+}
Added: openjpa/branches/openjpa_jpa-2.1/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/XROP.java
URL: http://svn.apache.org/viewvc/openjpa/branches/openjpa_jpa-2.1/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/XROP.java?rev=1683972&view=auto
==============================================================================
--- openjpa/branches/openjpa_jpa-2.1/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/XROP.java (added)
+++ openjpa/branches/openjpa_jpa-2.1/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/XROP.java Sun Jun 7 01:05:22 2015
@@ -0,0 +1,205 @@
+/*
+ * 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.jdbc.kernel;
+
+
+import org.apache.openjpa.jdbc.meta.QueryResultMapping;
+import org.apache.openjpa.jdbc.sql.ResultSetResult;
+import org.apache.openjpa.lib.rop.BatchedResultObjectProvider;
+import org.apache.openjpa.lib.rop.ResultObjectProvider;
+import org.apache.openjpa.util.InternalException;
+
+import java.sql.CallableStatement;
+import java.sql.ResultSet;
+import java.sql.SQLException;
+import java.util.List;
+
+/**
+ * Gets multiple Result Object Providers each with different mapping.
+ *
+ * @author Pinaki Poddar
+ *
+ */
+public class XROP implements BatchedResultObjectProvider {
+ private final CallableStatement stmt;
+ private final JDBCFetchConfiguration fetch;
+ private final List<QueryResultMapping> _multi;
+ private final List<Class<?>> _resultClasses;
+ private int index;
+ private final JDBCStore store;
+ // Result of first execution
+ private boolean executionResult;
+
+ public XROP(List<QueryResultMapping> mappings, List<Class<?>> classes,
+ JDBCStore store, JDBCFetchConfiguration fetch,
+ CallableStatement stmt) {
+ _multi = mappings;
+ _resultClasses = classes;
+ this.stmt = stmt;
+ this.fetch = fetch;
+ this.store = store;
+ }
+
+ /**
+ * Does not support random access.
+ */
+ @Override
+ public boolean supportsRandomAccess() {
+ return false;
+ }
+
+ /**
+ * Opens this provider by executing the underlying Statment.
+ * The result of execution is memorized.
+ */
+ @Override
+ public void open() throws Exception {
+ executionResult = stmt.execute();
+ }
+
+ /**
+ * Gets the current result set, wraps it with a {@link ResultSetResult}, then wraps
+ * again with appropriate ROP based on the result set mapping.
+ * <br>
+ * The ResultSet and the associated connection must not be closed.
+ *
+ * @return a provider or null if the underlying statement has no more results.
+ */
+ @Override
+ public ResultObjectProvider getResultObject() throws Exception {
+ ResultSet rs = stmt.getResultSet();
+ if (rs == null)
+ return null;
+
+ ResultSetResult res = new ResultSetResult(rs, store.getDBDictionary());
+ res.setCloseConnection(false);
+ res.setCloseStatement(false);
+ try {
+ if (_resultClasses != null && _resultClasses.size() > index) {
+ Class<?> mapping = _resultClasses.get(index);
+ if (mapping != null) {
+ return new GenericResultObjectProvider(mapping, store, fetch, res);
+ }
+ }
+ if (_multi != null && _multi.size() > index) {
+ QueryResultMapping mapping = _multi.get(index);
+ if (mapping != null) {
+ return new MappedQueryResultObjectProvider(mapping, store, fetch, res);
+ }
+ }
+ return new SQLProjectionResultObjectProvider(store, fetch, res, null);
+ } finally {
+ index++;
+ }
+ }
+
+
+ /**
+ * Closes the underlying statement.
+ */
+ @Override
+ public void close() throws Exception {
+ stmt.close();
+ }
+
+ /**
+ * Affirms if more result sets are available.
+ * <br>
+ * <b.NOTE</b>: The side effect is to advance to the statement's next result.
+ */
+ public boolean hasMoreResults() {
+ try {
+ return stmt.getMoreResults();
+ } catch (SQLException e) {
+ return false;
+ }
+ }
+
+ public boolean getExecutionResult() {
+ return executionResult;
+ }
+
+ /**
+ * Gets the update count, provided the current result of the statement is not a result set.
+ */
+ @Override
+ public int getUpdateCount() {
+ try {
+ return stmt.getUpdateCount();
+ } catch (SQLException e) {
+ return -1;
+ }
+ }
+
+ @Override
+ public Object getOut(String name) {
+ try {
+ return stmt.getObject(name);
+ } catch (SQLException e) {
+ return null;
+ }
+ }
+
+ @Override
+ public Object getOut(int position) {
+ try {
+ return stmt.getObject(position);
+ } catch (SQLException e) {
+ return null;
+ }
+ }
+
+ /**
+ * Throws exception.
+ */
+ @Override
+ public boolean next() throws Exception {
+ throw new InternalException();
+ }
+
+ /**
+ * Returns false.
+ */
+ @Override
+ public boolean absolute(int pos) throws Exception {
+ return false;
+ }
+
+ /**
+ * Returns {@code -1}.
+ */
+ @Override
+ public int size() throws Exception {
+ return -1;
+ }
+
+ /**
+ * Throws exception.
+ */
+ @Override
+ public void reset() throws Exception {
+ throw new InternalException();
+ }
+
+ @Override
+ public void handleCheckedException(Exception e) {
+ throw new RuntimeException(e);
+ }
+
+}
Modified: openjpa/branches/openjpa_jpa-2.1/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/meta/MappingRepository.java
URL: http://svn.apache.org/viewvc/openjpa/branches/openjpa_jpa-2.1/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/meta/MappingRepository.java?rev=1683972&r1=1683971&r2=1683972&view=diff
==============================================================================
--- openjpa/branches/openjpa_jpa-2.1/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/meta/MappingRepository.java (original)
+++ openjpa/branches/openjpa_jpa-2.1/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/meta/MappingRepository.java Sun Jun 7 01:05:22 2015
@@ -210,7 +210,7 @@ public class MappingRepository extends M
* Return the query result mapping for the given name.
*/
public QueryResultMapping getQueryResultMapping(Class<?> cls, String name, ClassLoader loader, boolean mustExist) {
- QueryResultMapping res = null;
+ QueryResultMapping res;
if (_locking) {
synchronized (this) {
res = getQueryResultMappingInternal(cls, name, loader);
@@ -232,13 +232,13 @@ public class MappingRepository extends M
// check cache
Object key = getQueryResultKey(cls, name);
- QueryResultMapping res = (QueryResultMapping) _results.get(key);
+ QueryResultMapping res = _results.get(key);
if (res != null)
return res;
// get metadata for class, which will find results in metadata file
if (cls != null && getMetaData(cls, envLoader, false) != null) {
- res = (QueryResultMapping) _results.get(key);
+ res = _results.get(key);
if (res != null)
return res;
}
@@ -250,7 +250,7 @@ public class MappingRepository extends M
.getResultSetMappingScope(name, envLoader);
// not in cache; load
getMetaDataFactory().load(cls, MODE_META | MODE_MAPPING, envLoader);
- return (QueryResultMapping) _results.get(key);
+ return _results.get(key);
}
/**
Modified: openjpa/branches/openjpa_jpa-2.1/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/meta/QueryResultMapping.java
URL: http://svn.apache.org/viewvc/openjpa/branches/openjpa_jpa-2.1/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/meta/QueryResultMapping.java?rev=1683972&r1=1683971&r2=1683972&view=diff
==============================================================================
--- openjpa/branches/openjpa_jpa-2.1/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/meta/QueryResultMapping.java (original)
+++ openjpa/branches/openjpa_jpa-2.1/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/meta/QueryResultMapping.java Sun Jun 7 01:05:22 2015
@@ -262,6 +262,7 @@ public class QueryResultMapping
private Map<List<MetaDataContext>, ColumnMap> _mappings = null;
private Map<List<MetaDataContext>, FetchInfo> _eager = null;
private FetchInfo _fetchInfo = null; // for top-level
+ private Collection<String> _constructorParams = null;
/**
* Supply candidate type on construction.
@@ -546,6 +547,13 @@ public class QueryResultMapping
info.excludes.clear(fm.getIndex());
}
}
+
+ public void addConstructorParam(final String name) {
+ if (_constructorParams == null) {
+ _constructorParams = new ArrayList<String>();
+ }
+ _constructorParams.add(name);
+ }
}
/**
Modified: openjpa/branches/openjpa_jpa-2.1/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/schema/Column.java
URL: http://svn.apache.org/viewvc/openjpa/branches/openjpa_jpa-2.1/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/schema/Column.java?rev=1683972&r1=1683971&r2=1683972&view=diff
==============================================================================
--- openjpa/branches/openjpa_jpa-2.1/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/schema/Column.java (original)
+++ openjpa/branches/openjpa_jpa-2.1/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/schema/Column.java Sun Jun 7 01:05:22 2015
@@ -62,6 +62,9 @@ public class Column
private DBIdentifier _typeName = DBIdentifier.NULL;
private int _javaType = JavaTypes.OBJECT;
private int _size = 0;
+ private int _precision = -1;
+ private int _scale = -1;
+ private int _radix = 10;
private int _decimals = 0;
private String _defaultStr = null;
private Object _default = null;
@@ -377,6 +380,29 @@ public class Column
_decimals = digits;
}
+ public int getPrecision() {
+ return _precision;
+ }
+
+ public void setPrecision(int p) {
+ _precision = p;
+ }
+
+ public int getScale() {
+ return _scale;
+ }
+
+ public void setScale(int s) {
+ _scale = s;
+ }
+ public int getRadix() {
+ return _radix;
+ }
+
+ public void setRadix(int r) {
+ _radix = r;
+ }
+
/**
* Return the default value set for the column, if any.
*/
@@ -492,6 +518,22 @@ public class Column
}
/**
+ * Sets nullability of this receiver by the given flag.
+ * @param flag one of the JDBC nullability flag namely
+ * <LI> {@link DatabaseMetaData#columnNullableUnknown} : not known if the column can be set to null value
+ * <LI> {@link DatabaseMetaData#columnNullable} : the column can be set to null value
+ * <LI> {@link DatabaseMetaData#columnNoNulls} : the column can not be set to null value
+ */
+ public void setNullability(short flag) {
+ switch (flag) {
+ case DatabaseMetaData.columnNullableUnknown : _notNull = null; break;
+ case DatabaseMetaData.columnNullable : _notNull = false; break;
+ case DatabaseMetaData.columnNoNulls : _notNull = true; break;
+
+ }
+ }
+
+ /**
* Whether this column is auto-assigned a value on insert.
*/
public boolean isAutoAssigned() {
@@ -610,7 +652,7 @@ public class Column
/**
* Set the column's 0-based index in the owning table.
*/
- void setIndex(int index) {
+ public void setIndex(int index) {
_index = index;
}
Modified: openjpa/branches/openjpa_jpa-2.1/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/sql/DBDictionary.java
URL: http://svn.apache.org/viewvc/openjpa/branches/openjpa_jpa-2.1/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/sql/DBDictionary.java?rev=1683972&r1=1683971&r2=1683972&view=diff
==============================================================================
--- openjpa/branches/openjpa_jpa-2.1/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/sql/DBDictionary.java (original)
+++ openjpa/branches/openjpa_jpa-2.1/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/sql/DBDictionary.java Sun Jun 7 01:05:22 2015
@@ -60,6 +60,7 @@ import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.Set;
+import java.util.TreeMap;
import javax.sql.DataSource;
@@ -4702,6 +4703,47 @@ public class DBDictionary
return toDBName(namingUtil.getGeneratedKeySequenceName(col, maxAutoAssignNameLength));
}
+ protected Map<String, StoredProcedure> _procs = new TreeMap<String, StoredProcedure>();
+
+ /**
+ * Gets the metadata of the stored procedure by the given name either from the cached version or
+ * by enquiring the database.
+ * @param meta the database meta data
+ * @param catalog the catalog name or null
+ * @param schema the schema name or null
+ * @param procedure the procedure name
+ * @return metadata about the named procedure or null
+ * @throws SQLException when metadata query goes wrong
+ */
+ public StoredProcedure getStoredProcedure(DatabaseMetaData meta, DBIdentifier catalog, DBIdentifier schema,
+ String procedure) throws SQLException {
+ if (_procs.containsKey(procedure)) {
+ return _procs.get(procedure);
+ }
+ ResultSet rs = meta.getProcedureColumns(
+ getCatalogNameForMetadata(catalog),
+ getSchemaNameForMetadata(schema),
+ procedure,
+ null);
+ StoredProcedure sp = null;
+ if (rs.next()) {
+ sp = new StoredProcedure(rs);
+ } else {
+ ResultSet rsExist = meta.getProcedures(
+ getCatalogNameForMetadata(catalog),
+ getSchemaNameForMetadata(schema),
+ procedure);
+ if (rsExist.next()) {
+ sp = new StoredProcedure((String) null);
+ sp.setCatalog(catalog);
+ sp.setSchema(schema);
+ sp.setName(procedure);
+ }
+ }
+ _procs.put(procedure, sp);
+ return sp;
+ }
+
///////////////////////////////
// Configurable implementation
///////////////////////////////
Modified: openjpa/branches/openjpa_jpa-2.1/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/sql/ResultSetResult.java
URL: http://svn.apache.org/viewvc/openjpa/branches/openjpa_jpa-2.1/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/sql/ResultSetResult.java?rev=1683972&r1=1683971&r2=1683972&view=diff
==============================================================================
--- openjpa/branches/openjpa_jpa-2.1/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/sql/ResultSetResult.java (original)
+++ openjpa/branches/openjpa_jpa-2.1/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/sql/ResultSetResult.java Sun Jun 7 01:05:22 2015
@@ -59,6 +59,7 @@ public class ResultSetResult
private final Statement _stmnt;
private final ResultSet _rs;
private final DBDictionary _dict;
+ private boolean _closeStatement = true;
private boolean _closeConn = true;
private int _row = -1;
private int _size = -1;
@@ -178,13 +179,17 @@ public class ResultSetResult
_closeConn = closeConn;
}
+ public void setCloseStatement(boolean closeStatement) {
+ _closeStatement = closeStatement;
+ }
+
public void close() {
super.close();
try {
_rs.close();
} catch (SQLException se) {
}
- if (_stmnt != null)
+ if (_stmnt != null && _closeStatement)
try {
_stmnt.close();
} catch (SQLException se) {
Added: openjpa/branches/openjpa_jpa-2.1/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/sql/StoredProcedure.java
URL: http://svn.apache.org/viewvc/openjpa/branches/openjpa_jpa-2.1/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/sql/StoredProcedure.java?rev=1683972&view=auto
==============================================================================
--- openjpa/branches/openjpa_jpa-2.1/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/sql/StoredProcedure.java (added)
+++ openjpa/branches/openjpa_jpa-2.1/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/sql/StoredProcedure.java Sun Jun 7 01:05:22 2015
@@ -0,0 +1,338 @@
+/*
+ * 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.jdbc.sql;
+
+import org.apache.openjpa.jdbc.identifier.DBIdentifier;
+import org.apache.openjpa.jdbc.schema.Column;
+import org.apache.openjpa.jdbc.schema.Schemas;
+import org.apache.openjpa.meta.MultiQueryMetaData;
+
+import java.lang.reflect.Method;
+import java.lang.reflect.Modifier;
+import java.sql.DatabaseMetaData;
+import java.sql.ResultSet;
+import java.sql.SQLException;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * Holds metadata about a Database Stored Procedure.
+ * This is different than {@link MultiQueryMetaData} which holds the metadata
+ * about what the user has specified.
+ * <br>
+ * An instance of this class can be constructed either by reading from database meta data
+ * or by programatic assignment. If an instance if created programmatically, then
+ * its SQL body or parameters can be added.
+ * <br>
+ * This class can generate the SQL statement to create, drop or delete this procedure.
+ *
+ *
+ * @author Pinaki Poddar
+ *
+ */
+public class StoredProcedure {
+ private DBIdentifier _catalog;
+ private DBIdentifier _schema;
+ private DBIdentifier _name;
+ private List<Column> _cols = new ArrayList<Column>();
+ private List<String> _params = new ArrayList<String>();
+
+
+ private List<String> _sql = new ArrayList<String>();
+ private final boolean _fromDatabase;
+
+ /**
+ * An enumeration on type of parameter for a Stored Procedure.
+ * The enumerted values has the same ordinal numbers as found
+ * in corresponding integer values in {@link DatabaseMetaData}.
+ */
+ public enum PARAM {UNKNOW, IN, INOUT, RESULT, OUT, RETURN}
+
+ public enum SQL {NONE,MODIFY,READ, CONTAINS};
+
+ /**
+ * Create a procedure of the given name.
+ */
+ public StoredProcedure(String name) {
+ _name = DBIdentifier.newProcedure(name);
+ _fromDatabase = false;
+ }
+
+ /**
+ * <pre>
+ *
+ * 1. PROCEDURE_CAT - String - the procedure catalog name
+ * 2. PROCEDURE_SCHEM - String - the procedure schema name (possibly null)
+ * 3. PROCEDURE_NAME - String - the procedure name
+ * 4. COLUMN_NAME - String - the name of the column
+ * 5. COLUMN_TYPE - short - the kind of column or parameter, as follows:
+ * DatabaseMetaData.procedureColumnUnknown - type unknown
+ * DatabaseMetaData.procedureColumnIn - an IN parameter
+ * DatabaseMetaData.procedureColumnInOut - an INOUT parameter
+ * DatabaseMetaData.procedureColumnOut - an OUT parameter
+ * DatabaseMetaData.procedureColumnReturn - a return value
+ * DatabaseMetaData.procedureReturnsResult - a result column in a result set
+ * 6. DATA_TYPE - int - the SQL type of the data, as in java.sql.Types
+ * 7. TYPE_NAME - String - the SQL type name, for a UDT it is fully qualified
+ * 8. PRECISION - int - the precision
+ * 9. LENGTH - int - the length of the data in bytes
+ * 10.SCALE - short - the scale for numeric types
+ * 11.RADIX - short - the Radix for numeric data (typically 2 or 10)
+ * 12.NULLABLE - short - can the data contain null:
+ * DatabaseMetaData.procedureNoNulls - NULLs not permitted
+ * DatabaseMetaData.procedureNullable - NULLs are permitted
+ * DatabaseMetaData.procedureNullableUnknown - NULL status unknown
+ * 13.REMARKS - String - an explanatory comment about the data item
+ * </pre>
+ **/
+
+ public StoredProcedure(ResultSet rs) throws SQLException {
+ _fromDatabase = true;
+ int i = 0;
+ do {
+ if (i == 0) {
+ // get stored procedure metadata
+ _catalog = DBIdentifier.newCatalog(rs.getString(1));
+ _schema = DBIdentifier.newSchema(rs.getString(2));
+ _name = DBIdentifier.newIdentifier(rs.getString(3), DBIdentifier.DBIdentifierType.PROCEDURE, false);
+ }
+ Column col = new Column();
+ _cols.add(col);
+ col.setIdentifier(DBIdentifier.newColumn(rs.getString(4)));
+ col.setFlag(rs.getShort(5), true);
+ col.setType(rs.getInt(6));
+ col.setTypeIdentifier(DBIdentifier.newConstant(rs.getString(7)));
+ col.setPrecision(rs.getInt(8));
+ col.setSize(rs.getInt(9));
+ col.setScale(rs.getInt(10));
+ col.setRadix(rs.getShort(11));
+ col.setNullability(rs.getShort(12));
+ col.setComment(rs.getString(13));
+ col.setIndex(i);
+ _params.add(col.getIdentifier().getName() + " " + col.getTypeIdentifier().getName());
+ i++;
+ } while (rs.next());
+ }
+
+ public void setCatalog(DBIdentifier catalog) {
+ this._catalog = catalog;
+ }
+
+ public void setSchema(DBIdentifier schema) {
+ this._schema = schema;
+ }
+
+ public void setName(String name) {
+ this._name = DBIdentifier.newIdentifier(name, DBIdentifier.DBIdentifierType.PROCEDURE, false);
+ }
+
+ public Column[] getInColumns() {
+ return getColumns((short)DatabaseMetaData.procedureColumnIn);
+ }
+
+ public Column[] getInOutColumns() {
+ return getColumns((short)DatabaseMetaData.procedureColumnInOut);
+ }
+
+ public Column[] getOutColumns() {
+ return getColumns((short)DatabaseMetaData.procedureColumnOut);
+ }
+
+ public Column[] getReturnColumns() {
+ return getColumns((short)DatabaseMetaData.procedureColumnReturn);
+ }
+
+ public Column[] getResultColumns() {
+ return getColumns((short)DatabaseMetaData.procedureColumnResult);
+ }
+
+ public Column[] getColumns() {
+ return _cols.toArray(new Column[_cols.size()]);
+ }
+
+ /**
+ * Counts the number of columns with the given flag.
+ * @param flag
+ * @return
+ */
+ int countColumn(short flag) {
+ int count = 0;
+ for (Column col : _cols) {
+ if (col.getFlag(flag)) count++;
+ }
+ return count;
+ }
+
+ Column[] getColumns(short flag) { // TODO: cache?
+ List<Column> cols = null;
+ for (Column col : _cols) {
+ if (col.getFlag(flag)) {
+ if (cols == null) cols = new ArrayList<Column>();
+ cols.add(col);
+ }
+ }
+ return cols == null ? Schemas.EMPTY_COLUMNS : cols.toArray(new Column[cols.size()]);
+ }
+
+
+ /**
+ * Gets the name of this procedure.
+ */
+ public String getName() {
+ return _name.getName();
+ }
+
+ /**
+ * Adds an {@code IN} parameter of the given name and type.
+ * @param var name of the variable
+ * @param typeName name of the SQL type e.g. {@code VARCAR(32)}
+ * @return this procedure instance
+ */
+ public StoredProcedure addParameter(String var, String typeName) {
+ return addParameter(PARAM.IN, var, typeName);
+ }
+ /**
+ * Adds the given parameter declaration.
+ *
+ * @param param type of parameter.
+ * @param var name of the variable
+ * @param typeName name of the SQL type e.g. {@code VARCAR(32)}
+ * @return this procedure instance
+ */
+ public StoredProcedure addParameter(PARAM param, String var, String typeName) {
+ assertMutable();
+
+ _params.add(param + " " + var + " " + typeName);
+ return this;
+ }
+
+ public StoredProcedure setLanguage(String language) {
+ _sql.add("LANGUAGE " + language);
+ return this;
+ }
+
+ /**
+ * Gets the SQL for creating this procedure.
+ */
+ public String getCreateSQL() {
+ StringBuilder buf = new StringBuilder();
+ buf.append("CREATE PROCEDURE ");
+ buf.append(_name);
+ buf.append(" (");
+ for (Iterator<String> p = _params.iterator(); p.hasNext();) {
+ buf.append(p.next());
+ buf.append(p.hasNext() ? "," : "");
+ }
+ buf.append(") ");
+ //buf.append("(");
+ for (String s : _sql) buf.append(s).append(" ");
+ //buf.append(")");
+
+ return buf.toString().trim();
+ }
+
+ /**
+ * Gets the SQL for dropping this procedure.
+ */
+ public String getDropSQL() {
+ return "DROP PROCEDURE " + _name;
+ }
+
+ /**
+ * Gets the SQL for calling this procedure.
+ */
+ public String getCallSQL() {
+ StringBuilder buf = new StringBuilder();
+ buf.append("CALL ");
+ buf.append(_name); buf.append(" (");
+ for (Iterator<String> p = _params.iterator(); p.hasNext();) {
+ p.next();
+ buf.append("?");
+ if (p.hasNext()) buf.append(",");
+ }
+ buf.append(")");
+ return buf.toString().trim();
+ }
+
+ /**
+ * Adds a read SQL statement via an external method.
+ */
+ public StoredProcedure setSQL(SQL sql) {
+ switch (sql) {
+ case CONTAINS : _sql.add("CONTAINS SQL"); break;
+ case NONE : _sql.add("NO SQL"); break;
+ case MODIFY : _sql.add("MODIFIES SQL DATA"); break;
+ case READ : _sql.add("READS SQL DATA"); break;
+ }
+ return this;
+ }
+
+ /**
+ * Sets the language whose parameter passing convention will be used to pass paramater values.
+ * @param lang
+ * @return
+ */
+ public StoredProcedure setParameterStyle(String lang) {
+ _sql.add("PARAMETER STYLE " + lang);
+ return this;
+ }
+
+ public StoredProcedure setExternalName(Class<?> cls, String method, Class<?>... paramTypes) {
+ assertStaticMethod(cls, method, paramTypes);
+ _sql.add("EXTERNAL NAME '" + cls.getName() + '.' + method + "'");
+ return this;
+ }
+
+ public StoredProcedure setResult(int i) {
+ return setResult(i, false);
+ }
+
+ public StoredProcedure setResult(int i, boolean dynamic) {
+ assertMutable();
+ _sql.add((dynamic ? "DYNAMIC " : "") + "RESULT SETS " + i);
+ return this;
+ }
+
+ private void assertStaticMethod(Class<?> cls, String method, Class<?>...paramTypes) {
+ try {
+ Method m = cls.getMethod(method, paramTypes);
+ if (m == null || !Modifier.isStatic(m.getModifiers())) {
+ throw new RuntimeException("No static method " + method + " with arguments "
+ + Arrays.toString(paramTypes) + " in " + cls);
+ }
+ } catch (Exception ex) {
+ throw new RuntimeException("No static method " + method + " with arguments "
+ + Arrays.toString(paramTypes) + " in " + cls, ex);
+ }
+ }
+
+ private void assertMutable() {
+ if (_fromDatabase) {
+ throw new IllegalStateException(this + " is not mutable");
+ }
+ }
+
+ public String toString() {
+ return getName();
+ }
+}
Modified: openjpa/branches/openjpa_jpa-2.1/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/QueryImpl.java
URL: http://svn.apache.org/viewvc/openjpa/branches/openjpa_jpa-2.1/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/QueryImpl.java?rev=1683972&r1=1683971&r2=1683972&view=diff
==============================================================================
--- openjpa/branches/openjpa_jpa-2.1/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/QueryImpl.java (original)
+++ openjpa/branches/openjpa_jpa-2.1/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/QueryImpl.java Sun Jun 7 01:05:22 2015
@@ -45,6 +45,7 @@ import org.apache.openjpa.kernel.exps.Pa
import org.apache.openjpa.kernel.exps.QueryExpressions;
import org.apache.openjpa.kernel.exps.Val;
import org.apache.openjpa.lib.log.Log;
+import org.apache.openjpa.lib.rop.BatchedResultObjectProvider;
import org.apache.openjpa.lib.rop.EagerResultList;
import org.apache.openjpa.lib.rop.ListResultList;
import org.apache.openjpa.lib.rop.MergedResultObjectProvider;
@@ -1226,6 +1227,9 @@ public class QueryImpl
protected Object toResult(StoreQuery q, StoreQuery.Executor ex,
ResultObjectProvider rop, StoreQuery.Range range)
throws Exception {
+ if (rop instanceof BatchedResultObjectProvider) {
+ return new QueryResultCallback(this, q, ex, (BatchedResultObjectProvider) rop, range);
+ }
// pack projections if necessary
String[] aliases = ex.getProjectionAliases(q);
if (!ex.isPacking(q)) {
Modified: openjpa/branches/openjpa_jpa-2.1/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/QueryLanguages.java
URL: http://svn.apache.org/viewvc/openjpa/branches/openjpa_jpa-2.1/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/QueryLanguages.java?rev=1683972&r1=1683971&r2=1683972&view=diff
==============================================================================
--- openjpa/branches/openjpa_jpa-2.1/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/QueryLanguages.java (original)
+++ openjpa/branches/openjpa_jpa-2.1/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/QueryLanguages.java Sun Jun 7 01:05:22 2015
@@ -34,6 +34,7 @@ import org.apache.openjpa.util.InternalE
public class QueryLanguages {
public static final String LANG_SQL = "openjpa.SQL";
+ public static final String LANG_STORED_PROC = "openjpa.StoredProcedure.SQL";
public static final String LANG_PREPARED_SQL = "openjpa.prepared.SQL";
public static final String LANG_METHODQL = "openjpa.MethodQL";
Added: openjpa/branches/openjpa_jpa-2.1/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/QueryResultCallback.java
URL: http://svn.apache.org/viewvc/openjpa/branches/openjpa_jpa-2.1/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/QueryResultCallback.java?rev=1683972&view=auto
==============================================================================
--- openjpa/branches/openjpa_jpa-2.1/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/QueryResultCallback.java (added)
+++ openjpa/branches/openjpa_jpa-2.1/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/QueryResultCallback.java Sun Jun 7 01:05:22 2015
@@ -0,0 +1,71 @@
+/*
+ * 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.kernel;
+
+import org.apache.openjpa.kernel.StoreQuery.Executor;
+import org.apache.openjpa.kernel.StoreQuery.Range;
+import org.apache.openjpa.lib.rop.BatchedResultObjectProvider;
+
+/**
+ * A callabck is used when a query results in multiple non-identical result sets.
+ * Designed to use with Stored Procedure Query.
+ *
+ * @author ppoddar
+ */
+public class QueryResultCallback {
+ private final StoreQuery storeQuery;
+ private final StoreQuery.Executor executor;
+ private final BatchedResultObjectProvider parent;
+ private final StoreQuery.Range range;
+ private final QueryImpl kernel;
+
+ public QueryResultCallback(QueryImpl kernel, StoreQuery storeQuery, Executor executor,
+ BatchedResultObjectProvider parent, Range range) {
+ super();
+ this.kernel = kernel;
+ this.storeQuery = storeQuery;
+ this.executor = executor;
+ this.parent = parent;
+ this.range = range;
+ }
+
+ public Object callback() throws Exception {
+ return kernel.toResult(storeQuery, executor, parent.getResultObject(), range);
+ }
+
+ public boolean hasMoreResults() {
+ return parent.hasMoreResults();
+ }
+
+ public boolean getExecutionResult() {
+ return parent.getExecutionResult();
+ }
+
+ public int getUpdateCount() {
+ return parent.getUpdateCount();
+ }
+
+ public Object getOut(int position) {
+ return parent.getOut(position);
+ }
+
+ public Object getOut(String name) {
+ return parent.getOut(name);
+ }
+}
Modified: openjpa/branches/openjpa_jpa-2.1/openjpa-kernel/src/main/java/org/apache/openjpa/meta/MetaDataRepository.java
URL: http://svn.apache.org/viewvc/openjpa/branches/openjpa_jpa-2.1/openjpa-kernel/src/main/java/org/apache/openjpa/meta/MetaDataRepository.java?rev=1683972&r1=1683971&r2=1683972&view=diff
==============================================================================
--- openjpa/branches/openjpa_jpa-2.1/openjpa-kernel/src/main/java/org/apache/openjpa/meta/MetaDataRepository.java (original)
+++ openjpa/branches/openjpa_jpa-2.1/openjpa-kernel/src/main/java/org/apache/openjpa/meta/MetaDataRepository.java Sun Jun 7 01:05:22 2015
@@ -2002,7 +2002,7 @@ public class MetaDataRepository implemen
return null;
// check cache
- QueryMetaData qm = (QueryMetaData) _queries.get(name);
+ QueryMetaData qm = _queries.get(name);
if (qm != null)
return qm;
@@ -2030,10 +2030,10 @@ public class MetaDataRepository implemen
public QueryMetaData[] getQueryMetaDatas() {
if (_locking) {
synchronized (this) {
- return (QueryMetaData[]) _queries.values().toArray(new QueryMetaData[_queries.size()]);
+ return _queries.values().toArray(new QueryMetaData[_queries.size()]);
}
} else {
- return (QueryMetaData[]) _queries.values().toArray(new QueryMetaData[_queries.size()]);
+ return _queries.values().toArray(new QueryMetaData[_queries.size()]);
}
}
@@ -2072,10 +2072,22 @@ public class MetaDataRepository implemen
}
}
+ public QueryMetaData addQueryMetaData(QueryMetaData meta) {
+ if (_locking) {
+ synchronized (this) {
+ final QueryMetaData queryMetaData = _queries.get(meta.getName());
+ return queryMetaData != null ? queryMetaData : _queries.put(meta.getName(), meta);
+ }
+ } else {
+ final QueryMetaData queryMetaData = _queries.get(meta.getName());
+ return queryMetaData != null ? queryMetaData : _queries.put(meta.getName(), meta);
+ }
+ }
+
/**
* Create a new query metadata instance.
*/
- protected QueryMetaData newQueryMetaData(Class<?> cls, String name) {
+ public QueryMetaData newQueryMetaData(Class<?> cls, String name) {
QueryMetaData meta =
new QueryMetaData(name, _conf.getCompatibilityInstance().getConvertPositionalParametersToNamed());
meta.setDefiningType(cls);
@@ -2118,7 +2130,7 @@ public class MetaDataRepository implemen
* Searches all cached query metadata by name.
*/
public QueryMetaData searchQueryMetaDataByName(String name) {
- return (QueryMetaData) _queries.get(name);
+ return _queries.get(name);
}
/**
Added: openjpa/branches/openjpa_jpa-2.1/openjpa-kernel/src/main/java/org/apache/openjpa/meta/MultiQueryMetaData.java
URL: http://svn.apache.org/viewvc/openjpa/branches/openjpa_jpa-2.1/openjpa-kernel/src/main/java/org/apache/openjpa/meta/MultiQueryMetaData.java?rev=1683972&view=auto
==============================================================================
--- openjpa/branches/openjpa_jpa-2.1/openjpa-kernel/src/main/java/org/apache/openjpa/meta/MultiQueryMetaData.java (added)
+++ openjpa/branches/openjpa_jpa-2.1/openjpa-kernel/src/main/java/org/apache/openjpa/meta/MultiQueryMetaData.java Sun Jun 7 01:05:22 2015
@@ -0,0 +1,189 @@
+/*
+ * 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.meta;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.apache.openjpa.kernel.QueryLanguages;
+
+
+
+/**
+ * Extends {@link QueryMetaData} to allow multiple {@link QueryMetaData#getResultType() result class} or
+ * {@link QueryMetaData#getResultSetMappingName() mapping names}.
+ * <br>
+ * Designed for mapping the results from a Stored Procudure that can produce more than one {@link java.sql.ResultSet},
+ * each being mapped with a different mapping specification.
+ *
+ *
+ * @author Pinaki Poddar
+ *
+ */
+@SuppressWarnings("serial")
+public class MultiQueryMetaData extends QueryMetaData {
+ private final String _procedureName;
+ private final boolean _isTemporary;
+ private final List<QueryMetaData> _parts = new ArrayList<QueryMetaData>();
+ private final List<Parameter> _params = new ArrayList<MultiQueryMetaData.Parameter>();
+
+ /**
+ * Create this meta data given a scope of definition, a logical identifier, a procedure name
+ * and whether its usage is temporary.
+ * @param scope defining scope
+ * @param logicalName name as an identifier
+ * @param procedureName name of the database procedure
+ */
+ public MultiQueryMetaData(Class<?> scope, String logicalName, String procedureName, boolean isTemporary) {
+ super(logicalName, false);
+ setLanguage(QueryLanguages.LANG_STORED_PROC);
+ setSource(null, scope, -1, null);
+ _procedureName = procedureName;
+ _isTemporary = isTemporary;
+ }
+
+ public String getProcedureName() {
+ return _procedureName;
+ }
+
+ public List<QueryMetaData> getComponents() {
+ return _parts;
+ }
+
+ /**
+ * Affirms if this metadata is ephimeral.
+ * Ephimenral metadata is removed from the repository after usage.
+ * @return
+ */
+ public boolean isEphimeral() {
+ return _isTemporary;
+ }
+
+ @Override
+ public void setResultSetMappingName(String name) {
+ throw new UnsupportedOperationException("Not allowed to set mapping name. It is automatically set");
+ }
+
+ @Override
+ public void setResultType(Class cls) {
+ throw new UnsupportedOperationException("Not allowed to set result type. It is automatically set");
+ }
+
+ public void addComponent(Class<?> resultClass) {
+ QueryMetaData part = newQueryMetaData();
+ part.setResultType(resultClass);
+ _parts.add(part);
+ }
+
+ public void addComponent(String mappingName) {
+ QueryMetaData part = newQueryMetaData();
+ part.setResultSetMappingName(mappingName);
+ _parts.add(part);
+ }
+
+ private QueryMetaData newQueryMetaData() {
+ QueryMetaData part = new QueryMetaData(getName() + "#" + _parts.size(), false);
+ part.setLanguage(getLanguage());
+ part.setSource(null, getDefiningType(), -1, null);
+ return part;
+ }
+
+
+ /**
+ * Gets the component metadata at the given part index.
+ * @param i a valid integer index
+ * @return
+ */
+ public QueryMetaData getComponent(int i) {
+ if (i < 0 || i >= _parts.size()) {
+ throw new ArrayIndexOutOfBoundsException("Invalid index " + i
+ + ". Available " + _parts.size() + " parts");
+ }
+ return _parts.get(i);
+ }
+
+ /**
+ * Gets the number of component metadata contained in this metada.
+ */
+ public int getComponentCount() {
+ return _parts.size();
+ }
+
+ /**
+ * Registers the given parameter.
+ * @param p
+ */
+ public void registerParameter(Parameter p) {
+ _params.add(p);
+ }
+
+ public List<Parameter> getParameters() {
+ return _params;
+ }
+
+ public int getParameterCount() {
+ return _params.size();
+ }
+
+
+ /**
+ * A parameter
+ *
+ */
+ public static class Parameter {
+ public enum Mode {IN,OUT,INOUT,CURSOR};
+ private final String name;
+ private final Class<?> type;
+ private final Mode mode;
+ private final int position;
+
+ public Parameter(String name, Class<?> type, Mode mode) {
+ this.name = name;
+ this.type = type;
+ this.mode = mode;
+ this.position = -1;
+ }
+
+ public Parameter(int position, Class<?> type, Mode mode) {
+ this.name = null;
+ this.type = type;
+ this.mode = mode;
+ this.position = position;
+ }
+
+ public int getPosition() {
+ return position;
+ }
+
+ public String getName() {
+ return name;
+ }
+
+ public Class<?> getType() {
+ return type;
+ }
+
+ public Mode getMode() {
+ return mode;
+ }
+ }
+
+
+
+}
Added: openjpa/branches/openjpa_jpa-2.1/openjpa-lib/src/main/java/org/apache/openjpa/lib/rop/BatchedResultObjectProvider.java
URL: http://svn.apache.org/viewvc/openjpa/branches/openjpa_jpa-2.1/openjpa-lib/src/main/java/org/apache/openjpa/lib/rop/BatchedResultObjectProvider.java?rev=1683972&view=auto
==============================================================================
--- openjpa/branches/openjpa_jpa-2.1/openjpa-lib/src/main/java/org/apache/openjpa/lib/rop/BatchedResultObjectProvider.java (added)
+++ openjpa/branches/openjpa_jpa-2.1/openjpa-lib/src/main/java/org/apache/openjpa/lib/rop/BatchedResultObjectProvider.java Sun Jun 7 01:05:22 2015
@@ -0,0 +1,64 @@
+/*
+ * 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.lib.rop;
+
+
+/**
+ * A provider for multiple result sets.
+ * This provider acts as a container of other result providers. The underlying providers
+ * contain the actual data and are {@link ResultObjectProvider#getResultObject() iterated}
+ * for the results, while this provider iterates over its underlying providers.
+ * <br>
+ * Designed for the specific purpose of getting results from the execution of Stored Procedures
+ * that can produce more than one result set and an optional update count. Few methods related
+ * to iterating multiple results and update count mirror the methods in JDBC {@link java.sql.Statement}.
+ * <br>
+ *
+ * @see org.apache.openjpa.kernel.QueryResultCallback
+ *
+ * @author Pinaki Poddar
+ *
+ */
+public interface BatchedResultObjectProvider extends ResultObjectProvider {
+ /**
+ * Gets the next result object provider from its batch.
+ */
+ ResultObjectProvider getResultObject() throws Exception;
+
+ /**
+ * Affirms if this batch contains more results.
+ */
+ boolean hasMoreResults();
+
+ /**
+ * Gets the result of executing the underlying JDBC statement.
+ * @return a boolean value whose semantics is same as {@link java.sql.PreparedStatement#execute()}.
+ */
+ boolean getExecutionResult();
+
+
+ /**
+ * Gets the count of records updated by the underlying JDBC statement.
+ * @return an integer value whose semantics is same as {@link java.sql.CallableStatement#getUpdateCount()}.
+ */
+ int getUpdateCount();
+
+ Object getOut(String name);
+ Object getOut(int position);
+}
Modified: openjpa/branches/openjpa_jpa-2.1/openjpa-persistence-jdbc/src/main/java/org/apache/openjpa/persistence/jdbc/AnnotationPersistenceMappingParser.java
URL: http://svn.apache.org/viewvc/openjpa/branches/openjpa_jpa-2.1/openjpa-persistence-jdbc/src/main/java/org/apache/openjpa/persistence/jdbc/AnnotationPersistenceMappingParser.java?rev=1683972&r1=1683971&r2=1683972&view=diff
==============================================================================
--- openjpa/branches/openjpa_jpa-2.1/openjpa-persistence-jdbc/src/main/java/org/apache/openjpa/persistence/jdbc/AnnotationPersistenceMappingParser.java (original)
+++ openjpa/branches/openjpa_jpa-2.1/openjpa-persistence-jdbc/src/main/java/org/apache/openjpa/persistence/jdbc/AnnotationPersistenceMappingParser.java Sun Jun 7 01:05:22 2015
@@ -34,6 +34,7 @@ import javax.persistence.AttributeOverri
import javax.persistence.AttributeOverrides;
import javax.persistence.CollectionTable;
import javax.persistence.ColumnResult;
+import javax.persistence.ConstructorResult;
import javax.persistence.DiscriminatorColumn;
import javax.persistence.DiscriminatorValue;
import javax.persistence.EntityResult;
@@ -620,6 +621,9 @@ public class AnnotationPersistenceMappin
entityResult.addMapping(field.name(), sColName.getName());
}
}
+ for (ConstructorResult constructorResult : anno.classes()) {
+ throw new UnsupportedOperationException("JPA 2.1, not yet impl");
+ }
for (ColumnResult column : anno.columns()) {
DBIdentifier sName = DBIdentifier.newColumn(column.name(), delimit());
result.addColumnResult(sName.getName());
@@ -1577,9 +1581,9 @@ public class AnnotationPersistenceMappin
}
if (xmlRootElementClass != null
&& StringUtils.isEmpty(pcols[i].columnDefinition())
- && (AccessController.doPrivileged(J2DoPrivHelper
+ && AccessController.doPrivileged(J2DoPrivHelper
.isAnnotationPresentAction(fm.getDeclaredType(),
- xmlRootElementClass))).booleanValue()) {
+ xmlRootElementClass)).booleanValue()) {
DBDictionary dict = ((MappingRepository) getRepository())
.getDBDictionary();
if (dict.supportsXMLColumn)
Modified: openjpa/branches/openjpa_jpa-2.1/openjpa-persistence-jdbc/src/main/java/org/apache/openjpa/persistence/jdbc/MappingTag.java
URL: http://svn.apache.org/viewvc/openjpa/branches/openjpa_jpa-2.1/openjpa-persistence-jdbc/src/main/java/org/apache/openjpa/persistence/jdbc/MappingTag.java?rev=1683972&r1=1683971&r2=1683972&view=diff
==============================================================================
--- openjpa/branches/openjpa_jpa-2.1/openjpa-persistence-jdbc/src/main/java/org/apache/openjpa/persistence/jdbc/MappingTag.java (original)
+++ openjpa/branches/openjpa_jpa-2.1/openjpa-persistence-jdbc/src/main/java/org/apache/openjpa/persistence/jdbc/MappingTag.java Sun Jun 7 01:05:22 2015
@@ -114,5 +114,5 @@ enum MappingTag {
X_MAPPING_OVERRIDES,
X_SECONDARY_TABLE,
X_SECONDARY_TABLES,
- X_TABLE,
+ X_TABLE
}
Added: openjpa/branches/openjpa_jpa-2.1/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/jdbc/procedure/TestStoredProcedure.java
URL: http://svn.apache.org/viewvc/openjpa/branches/openjpa_jpa-2.1/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/jdbc/procedure/TestStoredProcedure.java?rev=1683972&view=auto
==============================================================================
--- openjpa/branches/openjpa_jpa-2.1/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/jdbc/procedure/TestStoredProcedure.java (added)
+++ openjpa/branches/openjpa_jpa-2.1/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/jdbc/procedure/TestStoredProcedure.java Sun Jun 7 01:05:22 2015
@@ -0,0 +1,171 @@
+/*
+ * 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.jdbc.procedure;
+
+import org.apache.openjpa.jdbc.procedure.derby.Procedures;
+import org.apache.openjpa.jdbc.procedure.entity.EntityWithStoredProcedure;
+import org.apache.openjpa.jdbc.sql.DerbyDictionary;
+import org.apache.openjpa.persistence.test.DatabasePlatform;
+import org.apache.openjpa.persistence.test.SingleEMFTestCase;
+
+import java.util.Iterator;
+import javax.persistence.EntityManager;
+import javax.persistence.EntityTransaction;
+import javax.persistence.StoredProcedureQuery;
+
+@DatabasePlatform("org.apache.derby.jdbc.EmbeddedDriver")
+public class TestStoredProcedure extends SingleEMFTestCase {
+ @Override
+ public void setUp() {
+ setUp(
+ "openjpa.RuntimeUnenhancedClasses", "unsupported",
+ "openjpa.DynamicEnhancementAgent", "false",
+ EntityWithStoredProcedure.class, EntityWithStoredProcedure.Mapping2.class);
+ setSupportedDatabases(DerbyDictionary.class);
+ }
+
+ public void testSimple() {
+ Procedures.simpleCalled = false;
+
+ EntityManager em = emf.createEntityManager();
+ exec(em, "CREATE PROCEDURE TESTSIMPLE() " +
+ "PARAMETER STYLE JAVA LANGUAGE JAVA EXTERNAL NAME " +
+ "'" + Procedures.class.getName() + ".simple'");
+ StoredProcedureQuery procedure = em.createNamedStoredProcedureQuery("EntityWithStoredProcedure.simple");
+ assertFalse(procedure.execute());
+ em.close();
+ assertTrue(Procedures.simpleCalled);
+ }
+
+ public void testInParams() {
+ Procedures.inParamsInteger = -1;
+ Procedures.inParamsString = null;
+
+ EntityManager em = emf.createEntityManager();
+ exec(em, "CREATE PROCEDURE TESTINS(some_number INTEGER,some_string VARCHAR(255)) " +
+ "PARAMETER STYLE JAVA LANGUAGE JAVA EXTERNAL NAME " +
+ "'" + Procedures.class.getName() + ".inParams'");
+ StoredProcedureQuery procedure = em.createNamedStoredProcedureQuery("EntityWithStoredProcedure.inParams");
+ procedure.setParameter("SOME_NUMBER", 2015);
+ procedure.setParameter("SOME_STRING", "openjpa");
+ assertFalse(procedure.execute());
+ assertEquals(2015, Procedures.inParamsInteger);
+ assertEquals("openjpa", Procedures.inParamsString);
+
+ // null case
+ Procedures.inParamsInteger = -1;
+ Procedures.inParamsString = null;
+ StoredProcedureQuery procedure2 = em.createNamedStoredProcedureQuery("EntityWithStoredProcedure.inParams");
+ procedure2.setParameter("SOME_NUMBER", 20152);
+ assertFalse(procedure2.execute());
+ em.close();
+ assertEquals(20152, Procedures.inParamsInteger);
+ assertNull(Procedures.inParamsString);
+ }
+
+ public void testOut() {
+ EntityManager em = emf.createEntityManager();
+ exec(em, "CREATE PROCEDURE XTWO(IN some_number INTEGER,OUT x2 INTEGER) " +
+ "PARAMETER STYLE JAVA LANGUAGE JAVA EXTERNAL NAME " +
+ "'" + Procedures.class.getName() + ".x2'");
+ StoredProcedureQuery procedure = em.createNamedStoredProcedureQuery("EntityWithStoredProcedure.x2");
+ procedure.setParameter("SOME_NUMBER", 5);
+ assertFalse(procedure.execute());
+ // assertEquals(10, procedure.getOutputParameterValue("result")); // not impl by derby
+ assertEquals(10, procedure.getOutputParameterValue(2));
+ em.close();
+ }
+
+ public void testInOut() {
+ EntityManager em = emf.createEntityManager();
+ exec(em, "CREATE PROCEDURE XINOUT(INOUT P INTEGER) " +
+ "PARAMETER STYLE JAVA LANGUAGE JAVA EXTERNAL NAME " +
+ "'" + Procedures.class.getName() + ".inout'");
+ StoredProcedureQuery procedure = em.createNamedStoredProcedureQuery("EntityWithStoredProcedure.inout");
+ procedure.setParameter("P", 5);
+ assertFalse(procedure.execute());
+ // assertEquals(10, procedure.getOutputParameterValue("p")); // not impl by derby
+ assertEquals(10, procedure.getOutputParameterValue(1));
+ em.close();
+ }
+
+ public void testMapping() {
+ EntityManager em = emf.createEntityManager();
+ {
+ em.getTransaction().begin();
+ for (int i = 0; i < 2; i++) {
+ final EntityWithStoredProcedure entity = new EntityWithStoredProcedure();
+ entity.setId(1 + i);
+ entity.setName("#" + entity.getId());
+ em.persist(entity);
+ }
+ em.getTransaction().commit();
+ em.clear();
+ }
+
+ exec(em, "CREATE PROCEDURE MAPPING() " +
+ "PARAMETER STYLE JAVA LANGUAGE JAVA DYNAMIC RESULT SETS 2 EXTERNAL NAME " +
+ "'" + Procedures.class.getName() + ".mapping'");
+ StoredProcedureQuery procedure = em.createNamedStoredProcedureQuery("EntityWithStoredProcedure.mapping");
+ assertTrue(procedure.execute());
+ final Iterator r1 = procedure.getResultList().iterator();
+ final EntityWithStoredProcedure next1 = EntityWithStoredProcedure.class.cast(r1.next());
+ assertEquals(1, next1.getId());
+ assertEquals("#1", next1.getName());
+ assertNotNull(next1);
+ final EntityWithStoredProcedure next2 = EntityWithStoredProcedure.class.cast(r1.next());
+ assertNotNull(next2);
+ assertEquals(2, next2.getId());
+ assertEquals("#2", next2.getName());
+ assertFalse(r1.hasNext());
+ assertTrue(procedure.hasMoreResults());
+ final Iterator r2 = procedure.getResultList().iterator();
+ final EntityWithStoredProcedure.Mapping2 next3 = EntityWithStoredProcedure.Mapping2.class.cast(r2.next());
+ assertNotNull(next3);
+ assertFalse(r2.hasNext());
+ assertEquals(next2.getId(), next3.getId());
+ assertEquals(next2.getName(), next3.getName());
+
+ {
+ em.getTransaction().begin();
+ for (int i = 0; i < 2; i++) {
+ em.remove(em.find(EntityWithStoredProcedure.class, i + 1L));
+ }
+ em.getTransaction().commit();
+ em.clear();
+ }
+ em.close();
+ }
+
+ private void exec(final EntityManager em, final String proc) {
+ final EntityTransaction tx = em.getTransaction();
+ tx.begin();
+ try {
+ em.createNativeQuery(proc).executeUpdate();
+ tx.commit();
+ } catch (final Exception e) { // already exists or another error
+ e.printStackTrace();
+ try {
+ tx.rollback();
+ } catch (final Exception ignored) {
+ // no-op
+ }
+ }
+ }
+}
Added: openjpa/branches/openjpa_jpa-2.1/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/jdbc/procedure/derby/Procedures.java
URL: http://svn.apache.org/viewvc/openjpa/branches/openjpa_jpa-2.1/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/jdbc/procedure/derby/Procedures.java?rev=1683972&view=auto
==============================================================================
--- openjpa/branches/openjpa_jpa-2.1/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/jdbc/procedure/derby/Procedures.java (added)
+++ openjpa/branches/openjpa_jpa-2.1/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/jdbc/procedure/derby/Procedures.java Sun Jun 7 01:05:22 2015
@@ -0,0 +1,59 @@
+/*
+ * 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.jdbc.procedure.derby;
+
+import java.sql.Connection;
+import java.sql.DriverManager;
+import java.sql.ResultSet;
+
+import static junit.framework.Assert.fail;
+
+public final class Procedures {
+ public static boolean simpleCalled;
+
+ public static void simple() {
+ simpleCalled = true;
+ }
+
+ public static int inParamsInteger;
+ public static String inParamsString;
+
+ public static void inParams(int integer, String string) {
+ inParamsInteger = integer;
+ inParamsString = string;
+ }
+
+ public static void x2(int integer, int[] out) {
+ out[0] = integer * 2;
+ }
+
+ public static void inout(int[] p) {
+ p[0] = p[0] * 2;
+ }
+
+ public static void mapping(ResultSet[] r0, ResultSet[] r1) {
+ try {
+ Connection c = DriverManager.getConnection("jdbc:default:connection");
+ r0[0] = c.createStatement().executeQuery("SELECT * FROM EntityWithStoredProcedure order by id");
+ r1[0] = c.createStatement().executeQuery("SELECT * FROM EntityWithStoredProcedure where id = 2");
+ } catch (final Exception ex) {
+ fail(ex.getMessage());
+ }
+ }
+}
Added: openjpa/branches/openjpa_jpa-2.1/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/jdbc/procedure/entity/EntityWithStoredProcedure.java
URL: http://svn.apache.org/viewvc/openjpa/branches/openjpa_jpa-2.1/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/jdbc/procedure/entity/EntityWithStoredProcedure.java?rev=1683972&view=auto
==============================================================================
--- openjpa/branches/openjpa_jpa-2.1/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/jdbc/procedure/entity/EntityWithStoredProcedure.java (added)
+++ openjpa/branches/openjpa_jpa-2.1/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/jdbc/procedure/entity/EntityWithStoredProcedure.java Sun Jun 7 01:05:22 2015
@@ -0,0 +1,145 @@
+/*
+ * 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.jdbc.procedure.entity;
+
+import javax.persistence.Entity;
+import javax.persistence.EntityResult;
+import javax.persistence.Id;
+import javax.persistence.NamedStoredProcedureQueries;
+import javax.persistence.NamedStoredProcedureQuery;
+import javax.persistence.SqlResultSetMapping;
+import javax.persistence.SqlResultSetMappings;
+import javax.persistence.StoredProcedureParameter;
+
+import static javax.persistence.ParameterMode.INOUT;
+import static javax.persistence.ParameterMode.OUT;
+
+@Entity
+@NamedStoredProcedureQueries({
+ @NamedStoredProcedureQuery(
+ name = "EntityWithStoredProcedure.simple",
+ procedureName = "TESTSIMPLE"
+ ),
+ @NamedStoredProcedureQuery(
+ name = "EntityWithStoredProcedure.inParams",
+ procedureName = "TESTINS",
+ parameters = {
+ @StoredProcedureParameter(name = "SOME_NUMBER", type = Integer.class),
+ @StoredProcedureParameter(name = "SOME_STRING", type = String.class)
+ }
+ ),
+ @NamedStoredProcedureQuery(
+ name = "EntityWithStoredProcedure.x2",
+ procedureName = "XTWO",
+ parameters = {
+ @StoredProcedureParameter(name = "SOME_NUMBER", type = Integer.class),
+ @StoredProcedureParameter(name = "RESULT", type = Integer.class, mode = OUT)
+ }
+ ),
+ @NamedStoredProcedureQuery(
+ name = "EntityWithStoredProcedure.inout",
+ procedureName = "XINOUT",
+ parameters = {
+ @StoredProcedureParameter(name = "P ", type = Integer.class, mode = INOUT)
+ }
+ ),
+ @NamedStoredProcedureQuery(
+ name = "EntityWithStoredProcedure.mapping",
+ procedureName = "MAPPING",
+ resultSetMappings = {"mapping1", "mapping2"}
+ )
+})
+@SqlResultSetMappings({
+ @SqlResultSetMapping(
+ name = "mapping1",
+ entities = @EntityResult(entityClass = EntityWithStoredProcedure.class)
+ ),
+ @SqlResultSetMapping(
+ name = "mapping2",
+ entities = @EntityResult(entityClass = EntityWithStoredProcedure.Mapping2.class)
+ )
+})
+public class EntityWithStoredProcedure {
+ @Id
+ private long id;
+ private String name;
+
+ public EntityWithStoredProcedure() {
+ // no-op
+ }
+
+ public EntityWithStoredProcedure(final long id, final String name) {
+ this.id = id;
+ this.name = name;
+ }
+
+ public long getId() {
+ return id;
+ }
+
+ public void setId(long id) {
+ this.id = id;
+ }
+
+ public String getName() {
+ return name;
+ }
+
+ public void setName(String name) {
+ this.name = name;
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ if (this == o) return true;
+ if (o == null || getClass() != o.getClass()) return false;
+ EntityWithStoredProcedure that = (EntityWithStoredProcedure) o;
+ return id == that.id && name.equals(that.name);
+ }
+
+ @Override
+ public int hashCode() {
+ int result = (int) (id ^ (id >>> 32));
+ result = 31 * result + name.hashCode();
+ return result;
+ }
+
+ @Entity
+ public static class Mapping2 {
+ @Id
+ private long id;
+ private String name;
+
+ public long getId() {
+ return id;
+ }
+
+ public void setId(long id) {
+ this.id = id;
+ }
+
+ public String getName() {
+ return name;
+ }
+
+ public void setName(String name) {
+ this.name = name;
+ }
+ }
+}
Modified: openjpa/branches/openjpa_jpa-2.1/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/test/AbstractPersistenceTestCase.java
URL: http://svn.apache.org/viewvc/openjpa/branches/openjpa_jpa-2.1/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/test/AbstractPersistenceTestCase.java?rev=1683972&r1=1683971&r2=1683972&view=diff
==============================================================================
--- openjpa/branches/openjpa_jpa-2.1/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/test/AbstractPersistenceTestCase.java (original)
+++ openjpa/branches/openjpa_jpa-2.1/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/test/AbstractPersistenceTestCase.java Sun Jun 7 01:05:22 2015
@@ -223,9 +223,9 @@ public abstract class AbstractPersistenc
* Safely close the given factory.
*/
protected boolean closeEMF(EntityManagerFactory emf) {
- boolean brc = false;
+ boolean brc;
if (emf == null || !emf.isOpen()) {
- return brc;
+ return false;
}
try {
closeAllOpenEMs(emf);
Modified: openjpa/branches/openjpa_jpa-2.1/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/AbstractQuery.java
URL: http://svn.apache.org/viewvc/openjpa/branches/openjpa_jpa-2.1/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/AbstractQuery.java?rev=1683972&r1=1683971&r2=1683972&view=diff
==============================================================================
--- openjpa/branches/openjpa_jpa-2.1/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/AbstractQuery.java (original)
+++ openjpa/branches/openjpa_jpa-2.1/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/AbstractQuery.java Sun Jun 7 01:05:22 2015
@@ -83,6 +83,10 @@ public abstract class AbstractQuery<X> i
return result;
}
+ public boolean isProcedure() {
+ return QueryLanguages.LANG_STORED_PROC.equals(getLanguage());
+ }
+
public boolean isNative() {
return QueryLanguages.LANG_SQL.equals(getLanguage());
}
@@ -131,8 +135,8 @@ public abstract class AbstractQuery<X> i
if (pos < 1) {
throw new IllegalArgumentException(_loc.get("illegal-index", pos).getMessage());
}
- Parameter<?> param = null;
- if (isNative()) {
+ Parameter<?> param;
+ if (isNative() || isProcedure()) {
param = new ParameterImpl<Object>(pos, Object.class);
declareParameter(pos, param);
} else {