OPENJPA-2592 OPENJPA-2654 merge JPA-2.1 work originally done by rmannibucau in the openjpa-jpa-2.1 branch

Thanks to Romain for all the hard work!


git-svn-id: https://svn.apache.org/repos/asf/openjpa/trunk@1756850 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
Mark Struberg 2016-08-18 20:47:20 +00:00
commit 64e9f3868f
55 changed files with 2494 additions and 52 deletions

View File

@ -459,7 +459,7 @@ databaseName=${db.name}
<dependencies>
<dependency>
<groupId>org.apache.geronimo.specs</groupId>
<artifactId>geronimo-jpa_2.0_spec</artifactId>
<artifactId>geronimo-jpa_2.1_spec</artifactId>
<scope>compile</scope>
</dependency>
<dependency>

View File

@ -95,7 +95,7 @@
<version>4.0.2.GA</version>
<scope>test</scope>
<exclusions>
<!-- force usage of the geronimo-jpa_2.0_spec -->
<!-- force usage of the geronimo-jpa_2.1_spec -->
<exclusion>
<groupId>org.hibernate.java-persistence</groupId>
<artifactId>jpa-api</artifactId>

View File

@ -32,6 +32,16 @@ public class DummyProvider1 implements PersistenceProvider {
return null;
}
@Override
public void generateSchema(PersistenceUnitInfo info, Map map) {
// no-op
}
@Override
public boolean generateSchema(String persistenceUnitName, Map map) {
return false;
}
public EntityManagerFactory createEntityManagerFactory(String s, Map map) {
return null;
}

View File

@ -32,6 +32,16 @@ public class DummyProvider2 implements PersistenceProvider {
return null;
}
@Override
public void generateSchema(PersistenceUnitInfo info, Map map) {
// no-op
}
@Override
public boolean generateSchema(String persistenceUnitName, Map map) {
return false;
}
public EntityManagerFactory createEntityManagerFactory(String s, Map map) {
return null;
}

View File

@ -46,6 +46,7 @@ public class DBIdentifier extends IdentifierImpl implements Cloneable, Identifie
INDEX,
FOREIGN_KEY,
CONSTANT,
PROCEDURE,
NULL
}
@ -603,6 +604,10 @@ public class DBIdentifier extends IdentifierImpl implements Cloneable, Identifie
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.

View File

@ -910,6 +910,9 @@ public class JDBCStoreManager implements StoreManager, JDBCStore {
if (QueryLanguages.LANG_PREPARED_SQL.equals(language)) {
return new PreparedSQLStoreQuery(this);
}
if (QueryLanguages.LANG_STORED_PROC.equals(language)) {
return new StoredProcedureQuery(this);
}
return null;
}

View File

@ -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;
}
}
}

View File

@ -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);
}
}

View File

@ -210,7 +210,7 @@ public class MappingRepository extends MetaDataRepository {
* 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 MetaDataRepository {
// 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 MetaDataRepository {
.getResultSetMappingScope(name, envLoader);
// not in cache; load
getMetaDataFactory().load(cls, MODE_META | MODE_MAPPING, envLoader);
return (QueryResultMapping) _results.get(key);
return _results.get(key);
}
/**

View File

@ -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);
}
}
/**

View File

@ -63,6 +63,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;
@ -378,6 +381,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
return _notNull != null;
}
/**
* 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.
*/
@ -611,7 +653,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;
}

View File

@ -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;
@ -4704,6 +4705,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
///////////////////////////////

View File

@ -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) {

View File

@ -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();
}
}

View File

@ -44,7 +44,7 @@
</dependency>
<dependency>
<groupId>org.apache.geronimo.specs</groupId>
<artifactId>geronimo-jpa_2.0_spec</artifactId>
<artifactId>geronimo-jpa_2.1_spec</artifactId>
</dependency>
<dependency>
<groupId>org.apache.openjpa</groupId>

View File

@ -45,6 +45,7 @@ import org.apache.openjpa.kernel.exps.Path;
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;
@ -1233,6 +1234,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)) {

View File

@ -34,6 +34,7 @@ import org.apache.openjpa.util.InternalException;
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";

View File

@ -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);
}
}

View File

@ -2002,7 +2002,7 @@ public class MetaDataRepository implements PCRegistry.RegisterClassListener, Con
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 implements PCRegistry.RegisterClassListener, Con
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 implements PCRegistry.RegisterClassListener, Con
}
}
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 implements PCRegistry.RegisterClassListener, Con
* Searches all cached query metadata by name.
*/
public QueryMetaData searchQueryMetaDataByName(String name) {
return (QueryMetaData) _queries.get(name);
return _queries.get(name);
}
/**

View File

@ -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;
}
}
}

View File

@ -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);
}

View File

@ -34,6 +34,7 @@ import javax.persistence.AttributeOverride;
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 AnnotationPersistenceMappingParser
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());

View File

@ -114,5 +114,5 @@ enum MappingTag {
X_MAPPING_OVERRIDES,
X_SECONDARY_TABLE,
X_SECONDARY_TABLES,
X_TABLE,
X_TABLE
}

View File

@ -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
}
}
}
}

View File

@ -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());
}
}
}

View File

@ -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;
}
}
}

View File

@ -28,6 +28,8 @@ import javax.persistence.*;
import org.apache.openjpa.jdbc.meta.strats.*;
import org.apache.openjpa.persistence.*;
import org.apache.openjpa.persistence.jdbc.*;
import org.apache.openjpa.persistence.jdbc.ForeignKey;
import org.apache.openjpa.persistence.jdbc.Index;
import org.apache.openjpa.persistence.jdbc.OrderColumn;

View File

@ -223,9 +223,9 @@ public abstract class AbstractPersistenceTestCase extends TestCase {
* 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);

View File

@ -44,7 +44,7 @@
</dependency>
<dependency>
<groupId>org.apache.geronimo.specs</groupId>
<artifactId>geronimo-jpa_2.0_spec</artifactId>
<artifactId>geronimo-jpa_2.1_spec</artifactId>
</dependency>
<dependency>
<groupId>org.apache.geronimo.specs</groupId>

View File

@ -83,6 +83,10 @@ public abstract class AbstractQuery<X> implements OpenJPAQuerySPI<X> {
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> implements OpenJPAQuerySPI<X> {
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 {

View File

@ -63,6 +63,8 @@ import static org.apache.openjpa.persistence.MetaDataTag.QUERIES;
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.NamedNativeQueries;
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.LifecycleMetaData;
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 AnnotationPersistenceMetaDataParser
_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 AnnotationPersistenceMetaDataParser
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 AnnotationPersistenceMetaDataParser
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 AnnotationPersistenceMetaDataParser
* 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 AnnotationPersistenceMetaDataParser
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);
}
}
}

View File

@ -25,9 +25,7 @@ import java.util.HashMap;
import java.util.Map;
import java.util.Set;
import javax.persistence.Cache;
import javax.persistence.EntityManagerFactory;
import javax.persistence.PersistenceUnitUtil;
import javax.persistence.*;
import javax.persistence.spi.LoadState;
import org.apache.commons.lang.StringUtils;
@ -44,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;
@ -150,7 +149,7 @@ public class EntityManagerFactoryImpl
}
public OpenJPAEntityManagerSPI createEntityManager() {
return createEntityManager(null);
return createEntityManager((Map) null);
}
/**
@ -242,7 +241,17 @@ public class EntityManagerFactoryImpl
}
return em;
}
@Override
public EntityManager createEntityManager(SynchronizationType synchronizationType) {
throw new UnsupportedOperationException("JPA 2.1");
}
@Override
public EntityManager createEntityManager(SynchronizationType synchronizationType, Map map) {
throw new UnsupportedOperationException("JPA 2.1");
}
/**
* Create a new entity manager around the given broker.
*/
@ -354,6 +363,28 @@ public class EntityManagerFactoryImpl
return this;
}
@Override
public void addNamedQuery(String name, Query query) {
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
public <T> T unwrap(Class<T> cls) {
if (cls.isInstance(this)) {
return cls.cast(this);
}
throw new javax.persistence.PersistenceException(this + " is not a " + cls);
}
@Override
public <T> void addNamedEntityGraph(String graphName, EntityGraph<T> entityGraph) {
throw new UnsupportedOperationException("JPA 2.1");
}
/**
* Get the identifier for the specified entity. If not managed by any
* of the em's in this PU or not persistence capable, return null.

View File

@ -36,19 +36,24 @@ import java.util.Collection;
import java.util.EnumSet;
import java.util.HashMap;
import java.util.IdentityHashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
import javax.persistence.CacheRetrieveMode;
import javax.persistence.CacheStoreMode;
import javax.persistence.EntityGraph;
import javax.persistence.EntityManager;
import javax.persistence.FlushModeType;
import javax.persistence.LockModeType;
import javax.persistence.PessimisticLockScope;
import javax.persistence.Query;
import javax.persistence.StoredProcedureQuery;
import javax.persistence.Tuple;
import javax.persistence.TypedQuery;
import javax.persistence.criteria.CriteriaDelete;
import javax.persistence.criteria.CriteriaQuery;
import javax.persistence.criteria.CriteriaUpdate;
import javax.persistence.criteria.ParameterExpression;
import javax.persistence.metamodel.Metamodel;
@ -79,6 +84,8 @@ import org.apache.openjpa.lib.util.Closeable;
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;
@ -116,7 +123,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
}
@ -556,12 +564,24 @@ 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
("no-managed-trans"), null, null, false);
}
@Override
public boolean isJoinedToTransaction() {
return isActive() && _isJoinedToTransaction;
}
public void begin() {
_broker.begin();
}
@ -1077,6 +1097,64 @@ public class EntityManagerImpl
return newQueryImpl(kernelQuery, null);
}
@Override
public StoredProcedureQuery createNamedStoredProcedureQuery(String name) {
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) {
return newProcedure(procedureName, null);
}
@Override
public StoredProcedureQuery createStoredProcedureQuery(String procedureName, Class... resultClasses) {
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) {
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) {
return new QueryImpl<T>(this, _ret, kernelQuery, qmd);
}
@ -1633,7 +1711,17 @@ public class EntityManagerImpl
}
return facadeQuery;
}
@Override
public Query createQuery(CriteriaUpdate updateQuery) {
throw new UnsupportedOperationException("JPA 2.1");
}
@Override
public Query createQuery(CriteriaDelete deleteQuery) {
throw new UnsupportedOperationException("JPA 2.1");
}
public OpenJPAQuery createDynamicQuery(
org.apache.openjpa.persistence.query.QueryDefinition qdef) {
String jpql = _emf.getDynamicQueryBuilder().toJPQL(qdef);
@ -1790,6 +1878,26 @@ public class EntityManagerImpl
return _emf.getMetamodel();
}
@Override
public <T> EntityGraph<T> createEntityGraph(Class<T> rootType) {
throw new UnsupportedOperationException("JPA 2.1");
}
@Override
public EntityGraph<?> createEntityGraph(String graphName) {
throw new UnsupportedOperationException("JPA 2.1");
}
@Override
public EntityGraph<?> getEntityGraph(String graphName) {
throw new UnsupportedOperationException("JPA 2.1");
}
@Override
public <T> List<EntityGraph<? super T>> getEntityGraphs(Class<T> entityClass) {
throw new UnsupportedOperationException("JPA 2.1");
}
/**
* Sets the given property to the given value, reflectively.
*
@ -1892,4 +2000,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;
}
}

View File

@ -88,5 +88,8 @@ public enum MetaDataTag {
READ_ONLY,
TYPE,
REPLICATED,
OPENJPA_VERSION
OPENJPA_VERSION,
// JPA 2.1
STOREDPROCEDURE_QUERIES,
STOREDPROCEDURE_QUERY
}

View File

@ -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.NamedNativeQueries;
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) {
@ -418,6 +431,14 @@ public class PersistenceMetaDataFactory
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,
NamedNativeQuery... queries) {
for (NamedNativeQuery q : queries) {

View File

@ -220,6 +220,16 @@ public class PersistenceProviderImpl
}
}
@Override
public void generateSchema(PersistenceUnitInfo info, Map map) {
throw new UnsupportedOperationException("JPA 2.1");
}
@Override
public boolean generateSchema(String persistenceUnitName, Map map) {
throw new UnsupportedOperationException("JPA 2.1");
}
public void setPersistenceEnvironmentInfo(OpenJPAConfiguration conf, PersistenceUnitInfo pui) {
// OPENJPA-1460 Fix scope visibility of orm.xml when it is packaged in both ear file and war file
if (conf instanceof OpenJPAConfigurationImpl) {

View File

@ -129,7 +129,15 @@ public class StoreCacheImpl
public void evictAll() {
_cache.clear();
}
@Override
public <T> T unwrap(Class<T> cls) {
if (cls.isInstance(this)) {
return cls.cast(this);
}
throw new javax.persistence.PersistenceException(cls.getName() + " not supported");
}
public CacheStatistics getStatistics() {
return (_cache == null) ? null : _cache.getStatistics();
}

View File

@ -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;
}
}

View File

@ -601,7 +601,7 @@ public class XMLPersistenceMetaDataParser
@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())

View File

@ -29,13 +29,22 @@ import java.util.Map;
import java.util.Set;
import javax.persistence.Tuple;
import javax.persistence.criteria.CollectionJoin;
import javax.persistence.criteria.CompoundSelection;
import javax.persistence.criteria.CriteriaDelete;
import javax.persistence.criteria.CriteriaUpdate;
import javax.persistence.criteria.Expression;
import javax.persistence.criteria.From;
import javax.persistence.criteria.Join;
import javax.persistence.criteria.ListJoin;
import javax.persistence.criteria.MapJoin;
import javax.persistence.criteria.Order;
import javax.persistence.criteria.ParameterExpression;
import javax.persistence.criteria.Path;
import javax.persistence.criteria.Predicate;
import javax.persistence.criteria.Root;
import javax.persistence.criteria.Selection;
import javax.persistence.criteria.SetJoin;
import javax.persistence.criteria.Subquery;
import javax.persistence.criteria.Predicate.BooleanOperator;
import javax.persistence.metamodel.Attribute;
@ -108,6 +117,16 @@ public class CriteriaBuilderImpl implements OpenJPACriteriaBuilder, ExpressionPa
return new CriteriaQueryImpl<Tuple>(_model, Tuple.class);
}
@Override
public <T> CriteriaUpdate<T> createCriteriaUpdate(Class<T> targetEntity) {
throw new UnsupportedOperationException("JPA 2.1");
}
@Override
public <T> CriteriaDelete<T> createCriteriaDelete(Class<T> targetEntity) {
throw new UnsupportedOperationException("JPA 2.1");
}
public Object parse(String ql, ExpressionStoreQuery query) {
throw new AbstractMethodError();
}
@ -252,6 +271,41 @@ public class CriteriaBuilderImpl implements OpenJPACriteriaBuilder, ExpressionPa
return new Expressions.DatabaseFunction(name, type, args);
}
@Override
public <X, T, V extends T> Join<X, V> treat(Join<X, T> join, Class<V> type) {
throw new UnsupportedOperationException("JPA 2.1");
}
@Override
public <X, T, E extends T> CollectionJoin<X, E> treat(CollectionJoin<X, T> join, Class<E> type) {
throw new UnsupportedOperationException("JPA 2.1");
}
@Override
public <X, T, E extends T> SetJoin<X, E> treat(SetJoin<X, T> join, Class<E> type) {
throw new UnsupportedOperationException("JPA 2.1");
}
@Override
public <X, T, E extends T> ListJoin<X, E> treat(ListJoin<X, T> join, Class<E> type) {
throw new UnsupportedOperationException("JPA 2.1");
}
@Override
public <X, K, T, V extends T> MapJoin<X, K, V> treat(MapJoin<X, K, T> join, Class<V> type) {
throw new UnsupportedOperationException("JPA 2.1");
}
@Override
public <X, T extends X> Path<T> treat(Path<X> path, Class<T> type) {
throw new UnsupportedOperationException("JPA 2.1");
}
@Override
public <X, T extends X> Root<T> treat(Root<X> root, Class<T> type) {
throw new UnsupportedOperationException("JPA 2.1");
}
public Predicate ge(Expression<? extends Number> x,
Expression<? extends Number> y) {
return new Expressions.GreaterThanEqual(x,y);

View File

@ -29,6 +29,7 @@ import javax.persistence.criteria.ListJoin;
import javax.persistence.criteria.MapJoin;
import javax.persistence.criteria.Path;
import javax.persistence.criteria.PluralJoin;
import javax.persistence.criteria.Predicate;
import javax.persistence.criteria.SetJoin;
import javax.persistence.metamodel.Attribute;
import javax.persistence.metamodel.CollectionAttribute;
@ -138,7 +139,22 @@ abstract class Joins {
public Member<? extends Z, X> getMember() {
return (Member<? extends Z, X>) _member;
}
@Override
public Join<Z, X> on(Expression<Boolean> restriction) {
throw new UnsupportedOperationException("JPA 2.1");
}
@Override
public Join<Z, X> on(Predicate... restrictions) {
throw new UnsupportedOperationException("JPA 2.1");
}
@Override
public Predicate getOn() {
throw new UnsupportedOperationException("JPA 2.1");
}
/**
* Return the metamodel attribute corresponding to the join.
* @return metamodel attribute type corresponding to the join
@ -495,7 +511,22 @@ abstract class Joins {
public Collection(FromImpl<?,Z> parent, Members.CollectionAttributeImpl<? super Z, E> member, JoinType jt) {
super(parent, member, jt);
}
@Override
public CollectionJoin<Z, E> on(Expression<Boolean> restriction) {
throw new UnsupportedOperationException("JPA 2.1");
}
@Override
public CollectionJoin<Z, E> on(Predicate... restrictions) {
throw new UnsupportedOperationException("JPA 2.1");
}
@Override
public Predicate getOn() {
throw new UnsupportedOperationException("JPA 2.1");
}
public CollectionAttribute<? super Z, E> getModel() {
return (CollectionAttribute<? super Z, E>)_member;
}
@ -512,7 +543,22 @@ abstract class Joins {
public Set(FromImpl<?,Z> parent, Members.SetAttributeImpl<? super Z, E> member, JoinType jt) {
super(parent, member, jt);
}
@Override
public SetJoin<Z, E> on(Expression<Boolean> restriction) {
throw new UnsupportedOperationException("JPA 2.1");
}
@Override
public SetJoin<Z, E> on(Predicate... restrictions) {
throw new UnsupportedOperationException("JPA 2.1");
}
@Override
public Predicate getOn() {
throw new UnsupportedOperationException("JPA 2.1");
}
public SetAttribute<? super Z, E> getModel() {
return (SetAttribute<? super Z, E>)_member;
}
@ -531,7 +577,22 @@ abstract class Joins {
public List(FromImpl<?,Z> parent, Members.ListAttributeImpl<? super Z, E> member, JoinType jt) {
super(parent, member, jt);
}
@Override
public ListJoin<Z, E> on(Expression<Boolean> restriction) {
throw new UnsupportedOperationException("JPA 2.1");
}
@Override
public ListJoin<Z, E> on(Predicate... restrictions) {
throw new UnsupportedOperationException("JPA 2.1");
}
@Override
public Predicate getOn() {
throw new UnsupportedOperationException("JPA 2.1");
}
public ListAttribute<? super Z, E> getModel() {
return (ListAttribute<? super Z, E>)_member;
}
@ -556,7 +617,22 @@ abstract class Joins {
public Map(FromImpl<?,Z> parent, Members.MapAttributeImpl<? super Z, K,V> member, JoinType jt) {
super(parent, member, jt);
}
@Override
public MapJoin<Z, K, V> on(Expression<Boolean> restriction) {
throw new UnsupportedOperationException("JPA 2.1");
}
@Override
public MapJoin<Z, K, V> on(Predicate... restrictions) {
throw new UnsupportedOperationException("JPA 2.1");
}
@Override
public Predicate getOn() {
throw new UnsupportedOperationException("JPA 2.1");
}
public MapAttribute<? super Z, K,V> getModel() {
return (MapAttribute<? super Z, K,V>) _member;
}

View File

@ -27,6 +27,7 @@ import java.util.concurrent.CopyOnWriteArraySet;
import javax.persistence.criteria.AbstractQuery;
import javax.persistence.criteria.CollectionJoin;
import javax.persistence.criteria.CommonAbstractCriteria;
import javax.persistence.criteria.Expression;
import javax.persistence.criteria.Join;
import javax.persistence.criteria.ListJoin;
@ -94,7 +95,12 @@ class SubqueryImpl<T> extends ExpressionImpl<T> implements Subquery<T> {
public AbstractQuery<?> getParent() {
return _parent;
}
@Override
public CommonAbstractCriteria getContainingQuery() {
return getParent();
}
/**
* Gets the captive query to which this subquery delegates.
*/

View File

@ -140,7 +140,7 @@
<include>commons-dbcp:commons-dbcp</include>
<include>org.apache.geronimo.specs:geronimo-jta_1.1_spec</include>
<include>org.apache.geronimo.specs:geronimo-jpa_2.0_spec</include>
<include>org.apache.geronimo.specs:geronimo-jpa_2.1_spec</include>
<include>org.apache.geronimo.specs:geronimo-jms_1.1_spec</include>
<include>org.apache.geronimo.specs:geronimo-validation_1.0_spec</include>
<include>org.apache.bval:org.apache.bval.bundle</include>

View File

@ -79,7 +79,7 @@
<include>commons-dbcp:commons-dbcp</include>
<include>org.apache.geronimo.specs:geronimo-jta_1.1_spec</include>
<include>org.apache.geronimo.specs:geronimo-jpa_2.0_spec</include>
<include>org.apache.geronimo.specs:geronimo-jpa_2.1_spec</include>
<include>org.apache.geronimo.specs:geronimo-jms_1.1_spec</include>
<include>org.apache.geronimo.specs:geronimo-validation_1.0_spec</include>
<include>org.apache.bval:org.apache.bval.bundle</include>

View File

@ -49,7 +49,7 @@
</dependency>
<dependency>
<groupId>org.apache.geronimo.specs</groupId>
<artifactId>geronimo-jpa_2.0_spec</artifactId>
<artifactId>geronimo-jpa_2.1_spec</artifactId>
<scope>test</scope>
</dependency>
<dependency>

View File

@ -30,7 +30,7 @@
<dependencies>
<dependency>
<groupId>org.apache.geronimo.specs</groupId>
<artifactId>geronimo-jpa_2.0_spec</artifactId>
<artifactId>geronimo-jpa_2.1_spec</artifactId>
</dependency>
<dependency>
<groupId>org.apache.geronimo.specs</groupId>

View File

@ -115,7 +115,7 @@
<dependency>
<groupId>org.apache.geronimo.specs</groupId>
<artifactId>geronimo-jpa_2.0_spec</artifactId>
<artifactId>geronimo-jpa_2.1_spec</artifactId>
</dependency>
<dependency>
<groupId>org.apache.geronimo.specs</groupId>

View File

@ -37,7 +37,7 @@
<dependency>
<groupId>org.apache.geronimo.specs</groupId>
<artifactId>geronimo-jpa_2.0_spec</artifactId>
<artifactId>geronimo-jpa_2.1_spec</artifactId>
</dependency>
<dependency>
<groupId>org.apache.geronimo.specs</groupId>

View File

@ -43,7 +43,7 @@
<dependencies>
<dependency>
<groupId>org.apache.geronimo.specs</groupId>
<artifactId>geronimo-jpa_2.0_spec</artifactId>
<artifactId>geronimo-jpa_2.1_spec</artifactId>
</dependency>
<dependency>
<groupId>org.apache.geronimo.specs</groupId>

View File

@ -37,7 +37,7 @@
<dependencies>
<dependency>
<groupId>org.apache.geronimo.specs</groupId>
<artifactId>geronimo-jpa_2.0_spec</artifactId>
<artifactId>geronimo-jpa_2.1_spec</artifactId>
</dependency>
<dependency>
<groupId>org.apache.geronimo.specs</groupId>

View File

@ -36,7 +36,7 @@
<dependencies>
<dependency>
<groupId>org.apache.geronimo.specs</groupId>
<artifactId>geronimo-jpa_2.0_spec</artifactId>
<artifactId>geronimo-jpa_2.1_spec</artifactId>
</dependency>
<dependency>
<groupId>org.apache.geronimo.specs</groupId>

View File

@ -36,7 +36,7 @@
<dependencies>
<dependency>
<groupId>org.apache.geronimo.specs</groupId>
<artifactId>geronimo-jpa_2.0_spec</artifactId>
<artifactId>geronimo-jpa_2.1_spec</artifactId>
</dependency>
<dependency>
<groupId>org.apache.geronimo.specs</groupId>

View File

@ -36,7 +36,7 @@
<dependencies>
<dependency>
<groupId>org.apache.geronimo.specs</groupId>
<artifactId>geronimo-jpa_2.0_spec</artifactId>
<artifactId>geronimo-jpa_2.1_spec</artifactId>
</dependency>
<dependency>
<groupId>org.apache.geronimo.specs</groupId>

View File

@ -524,8 +524,8 @@
</dependency>
<dependency>
<groupId>org.apache.geronimo.specs</groupId>
<artifactId>geronimo-jpa_2.0_spec</artifactId>
<version>1.1</version>
<artifactId>geronimo-jpa_2.1_spec</artifactId>
<version>1.0-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>org.apache.geronimo.specs</groupId>

View File

@ -40,7 +40,7 @@ set JAVAC=%JAVA_HOME%\bin\javac
@rem Compiler classpath shown for a typical OpenJPA development environment in Windows.
@rem The essential aspect is openjpa libraries must be in the compiler's classpath.
set M_REPO="%USERPROFILE%\.m2\repository"
set SPEC=geronimo-jpa_2.0_spec
set SPEC=geronimo-jpa_2.1_spec
set VERSION=1.0-EA9-SNAPSHOT
set JPA_LIB=%M_REPO%\org\apache\geronimo\specs\%SPEC%\%VERSION%\%SPEC%-%VERSION%.jar