You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@openjpa.apache.org by pp...@apache.org on 2013/05/08 23:38:30 UTC
svn commit: r1480473 [2/2] - in /openjpa/sandboxes/21:
openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/
openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/meta/
openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/sql/
openjpa-jdbc/src/test/jav...
Modified: openjpa/sandboxes/21/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/AnnotationPersistenceMetaDataParser.java
URL: http://svn.apache.org/viewvc/openjpa/sandboxes/21/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/AnnotationPersistenceMetaDataParser.java?rev=1480473&r1=1480472&r2=1480473&view=diff
==============================================================================
--- openjpa/sandboxes/21/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/AnnotationPersistenceMetaDataParser.java (original)
+++ openjpa/sandboxes/21/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/AnnotationPersistenceMetaDataParser.java Wed May 8 21:38:29 2013
@@ -94,6 +94,9 @@ import javax.persistence.AccessType;
import javax.persistence.Basic;
import javax.persistence.Cacheable;
import javax.persistence.CascadeType;
+import javax.persistence.Convert;
+import javax.persistence.Converter;
+import javax.persistence.Converts;
import javax.persistence.ElementCollection;
import javax.persistence.Embeddable;
import javax.persistence.Embedded;
@@ -120,9 +123,12 @@ import javax.persistence.NamedNativeQuer
import javax.persistence.NamedNativeQuery;
import javax.persistence.NamedQueries;
import javax.persistence.NamedQuery;
+import javax.persistence.NamedStoredProcedureQueries;
+import javax.persistence.NamedStoredProcedureQuery;
import javax.persistence.OneToMany;
import javax.persistence.OneToOne;
import javax.persistence.OrderBy;
+import javax.persistence.ParameterMode;
import javax.persistence.PostLoad;
import javax.persistence.PostPersist;
import javax.persistence.PostRemove;
@@ -159,6 +165,7 @@ import org.apache.openjpa.meta.MetaDataR
import org.apache.openjpa.meta.Order;
import org.apache.openjpa.meta.QueryMetaData;
import org.apache.openjpa.meta.SequenceMetaData;
+import org.apache.openjpa.meta.MultiQueryMetaData;
import org.apache.openjpa.meta.UpdateStrategies;
import org.apache.openjpa.meta.ValueMetaData;
import org.apache.openjpa.meta.ValueStrategies;
@@ -181,7 +188,7 @@ import serp.util.Strings;
public class AnnotationPersistenceMetaDataParser
implements MetaDataModes {
- private static final Localizer _loc = Localizer.forPackage
+ protected static final Localizer _loc = Localizer.forPackage
(AnnotationPersistenceMetaDataParser.class);
private static final Map<Class<?>, MetaDataTag> _tags =
@@ -189,12 +196,14 @@ public class AnnotationPersistenceMetaDa
static {
_tags.put(Access.class, ACCESS);
+ _tags.put(Convert.class, MetaDataTag.CONVERT);
+ _tags.put(Converter.class, MetaDataTag.CONVERTER);
+ _tags.put(Converts.class, MetaDataTag.CONVERTS);
_tags.put(Cacheable.class, CACHEABLE);
_tags.put(EmbeddedId.class, EMBEDDED_ID);
_tags.put(EntityListeners.class, ENTITY_LISTENERS);
_tags.put(ExcludeDefaultListeners.class, EXCLUDE_DEFAULT_LISTENERS);
- _tags.put(ExcludeSuperclassListeners.class,
- EXCLUDE_SUPERCLASS_LISTENERS);
+ _tags.put(ExcludeSuperclassListeners.class, EXCLUDE_SUPERCLASS_LISTENERS);
_tags.put(FlushModeType.class, FLUSH_MODE);
_tags.put(GeneratedValue.class, GENERATED_VALUE);
_tags.put(Id.class, ID);
@@ -239,7 +248,7 @@ public class AnnotationPersistenceMetaDa
private final OpenJPAConfiguration _conf;
private final Log _log;
- private MetaDataRepository _repos = null;
+ protected MetaDataRepository _repos = null;
private ClassLoader _envLoader = null;
private boolean _override = false;
private int _mode = MODE_NONE;
@@ -448,6 +457,8 @@ public class AnnotationPersistenceMetaDa
MetaDataTag tag;
for (Annotation anno : pkg.getDeclaredAnnotations()) {
+ System.err.println("parsePackageAnnotations( " + _cls.getName() + ") : "
+ + anno.annotationType().getClass().getSimpleName());
tag = _tags.get(anno.annotationType());
if (tag == null) {
handleUnknownPackageAnnotation(pkg, anno);
@@ -457,13 +468,13 @@ public class AnnotationPersistenceMetaDa
switch (tag) {
case NATIVE_QUERIES:
if (isQueryMode() && (pkgMode & MODE_QUERY) == 0)
- parseNamedNativeQueries(pkg,
- ((NamedNativeQueries) anno).value());
+ parseNamedNativeQueries(pkg, ((NamedNativeQueries) anno).value());
break;
case NATIVE_QUERY:
if (isQueryMode() && (pkgMode & MODE_QUERY) == 0)
parseNamedNativeQueries(pkg, (NamedNativeQuery) anno);
break;
+
case QUERIES:
if (isQueryMode() && (pkgMode & MODE_QUERY) == 0)
parseNamedQueries(pkg, ((NamedQueries) anno).value());
@@ -572,6 +583,8 @@ public class AnnotationPersistenceMetaDa
Collection<LifecycleCallbacks>[] listeners = null;
MetaDataTag tag;
for (Annotation anno : _cls.getDeclaredAnnotations()) {
+ System.err.println("parseClassAnnotations( " + _cls.getName() + ") : "
+ + anno.annotationType().getSimpleName());
tag = _tags.get(anno.annotationType());
if (tag == null) {
handleUnknownClassAnnotation(meta, anno);
@@ -604,8 +617,7 @@ public class AnnotationPersistenceMetaDa
break;
case NATIVE_QUERIES:
if (isQueryMode() && (meta.getSourceMode() & MODE_QUERY)==0)
- parseNamedNativeQueries(_cls,
- ((NamedNativeQueries) anno).value());
+ parseNamedNativeQueries(_cls, ((NamedNativeQueries) anno).value());
break;
case NATIVE_QUERY:
if (isQueryMode() && (meta.getSourceMode() & MODE_QUERY)==0)
@@ -1844,28 +1856,18 @@ public class AnnotationPersistenceMetaDa
* Parse @NamedQuery.
*/
private void parseNamedQueries(AnnotatedElement el, NamedQuery... queries) {
- QueryMetaData meta;
for (NamedQuery query : queries) {
if (StringUtils.isEmpty(query.name()))
throw new MetaDataException(_loc.get("no-query-name", el));
if (StringUtils.isEmpty(query.query()))
- throw new MetaDataException(_loc.get("no-query-string",
- query.name(), el));
+ throw new MetaDataException(_loc.get("no-query-string", query.name(), el));
if (_log.isTraceEnabled())
_log.trace(_loc.get("parse-query", query.name()));
- meta = getRepository().searchQueryMetaDataByName(query.name());
- if (meta != null) {
- Class<?> definingType = meta.getDefiningType();
- if ((definingType == null || definingType != _cls)
- && _log.isWarnEnabled()) {
- _log.warn(_loc.get("dup-query", query.name(), el,
- definingType));
- }
- continue;
- }
- meta = getRepository().addQueryMetaData(_cls, query.name());
+ QueryMetaData meta = new QueryMetaData(_cls, query.name());
+ addQueryMetaData(el, meta);
+
meta.setLanguage(JPQLParser.LANG_JPQL);
meta.setQueryString(query.query());
for (QueryHint hint : query.hints())
@@ -1885,6 +1887,20 @@ public class AnnotationPersistenceMetaDa
meta.setSourceMode(MODE_QUERY);
}
}
+
+ /**
+ * Adds the given query meta.
+ * @param meta a query meta data
+ * @exception throws exception if a query meta data with the same name of the given meta
+ * already exists in the repository.
+ */
+ protected void addQueryMetaData(Object location, QueryMetaData meta) {
+ QueryMetaData existing = getRepository().addQueryMetaData(meta);
+ if (existing != null) {
+ Class<?> scope = existing.getDefiningType();
+ throw new UserException(_loc.get("dup-query", meta.getName(), location, scope));
+ }
+ }
/**
* A private worker method that calculates the lock mode for an individual NamedQuery. If the NamedQuery is
@@ -1912,33 +1928,48 @@ public class AnnotationPersistenceMetaDa
return lmt;
}
+ 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());
+
+ }
/**
* Parse @NamedNativeQuery.
*/
- private void parseNamedNativeQueries(AnnotatedElement el,
- NamedNativeQuery... queries) {
- QueryMetaData meta;
+ private void parseNamedNativeQueries(AnnotatedElement el, NamedNativeQuery... queries) {
for (NamedNativeQuery query : queries) {
if (StringUtils.isEmpty(query.name()))
- throw new MetaDataException(_loc.get("no-native-query-name",
- el));
+ throw new MetaDataException(_loc.get("no-native-query-name", el));
if (StringUtils.isEmpty(query.query()))
- throw new MetaDataException(_loc.get("no-native-query-string",
- query.name(), el));
+ throw new MetaDataException(_loc.get("no-native-query-string", query.name(), el));
if (_log.isTraceEnabled())
_log.trace(_loc.get("parse-native-query", query.name()));
- meta = getRepository().searchQueryMetaDataByName(query.name());
- if (meta != null) {
- Class<?> defType = meta.getDefiningType();
- if ((defType != _cls) && _log.isWarnEnabled()) {
- _log.warn(_loc.get("dup-query", query.name(), el, defType));
- }
- continue;
- }
-
- meta = getRepository().addQueryMetaData(null, query.name());
+ QueryMetaData meta = new QueryMetaData(_cls, query.name());
+ addQueryMetaData(el, meta);
+
meta.setLanguage(QueryLanguages.LANG_SQL);
meta.setQueryString(query.query());
Class<?> res = query.resultClass();
@@ -1949,17 +1980,8 @@ public class AnnotationPersistenceMetaDa
if (!StringUtils.isEmpty(query.resultSetMapping()))
meta.setResultSetMappingName(query.resultSetMapping());
- for (QueryHint hint : query.hints())
- meta.addHint(hint.name(), hint.value());
-
- 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);
+ addHints(meta, query.hints());
+ addSourceInfo(el, meta);
}
}
Modified: openjpa/sandboxes/21/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/EntityManagerFactoryImpl.java
URL: http://svn.apache.org/viewvc/openjpa/sandboxes/21/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/EntityManagerFactoryImpl.java?rev=1480473&r1=1480472&r2=1480473&view=diff
==============================================================================
--- openjpa/sandboxes/21/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/EntityManagerFactoryImpl.java (original)
+++ openjpa/sandboxes/21/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/EntityManagerFactoryImpl.java Wed May 8 21:38:29 2013
@@ -47,6 +47,7 @@ import org.apache.openjpa.lib.conf.Value
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.QueryMetaData;
import org.apache.openjpa.persistence.criteria.CriteriaBuilderImpl;
import org.apache.openjpa.persistence.criteria.OpenJPACriteriaBuilder;
import org.apache.openjpa.persistence.meta.MetamodelImpl;
@@ -417,9 +418,8 @@ public class EntityManagerFactoryImpl
@Override
public void addNamedQuery(String name, Query query) {
org.apache.openjpa.kernel.Query kernelQuery = ((QueryImpl<?>)query).getDelegate();
-
- _factory.getConfiguration().getMetaDataRepositoryInstance()
- .addQueryMetaData(name, kernelQuery);
+ QueryMetaData meta = new QueryMetaData(name, kernelQuery);
+ _factory.getConfiguration().getMetaDataRepositoryInstance().addQueryMetaData(meta);
}
Modified: openjpa/sandboxes/21/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/EntityManagerImpl.java
URL: http://svn.apache.org/viewvc/openjpa/sandboxes/21/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/EntityManagerImpl.java?rev=1480473&r1=1480472&r2=1480473&view=diff
==============================================================================
--- openjpa/sandboxes/21/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/EntityManagerImpl.java (original)
+++ openjpa/sandboxes/21/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/EntityManagerImpl.java Wed May 8 21:38:29 2013
@@ -46,8 +46,10 @@ import javax.persistence.EntityGraph;
import javax.persistence.EntityManager;
import javax.persistence.FlushModeType;
import javax.persistence.LockModeType;
+import javax.persistence.NamedStoredProcedureQuery;
import javax.persistence.PessimisticLockScope;
import javax.persistence.Query;
+import javax.persistence.SqlResultSetMapping;
import javax.persistence.StoredProcedureQuery;
import javax.persistence.TypedQuery;
import javax.persistence.criteria.CriteriaDelete;
@@ -83,8 +85,10 @@ import org.apache.openjpa.lib.util.Close
import org.apache.openjpa.lib.util.Localizer;
import org.apache.openjpa.meta.ClassMetaData;
import org.apache.openjpa.meta.FieldMetaData;
+import org.apache.openjpa.meta.MetaDataRepository;
import org.apache.openjpa.meta.QueryMetaData;
import org.apache.openjpa.meta.SequenceMetaData;
+import org.apache.openjpa.meta.MultiQueryMetaData;
import org.apache.openjpa.persistence.criteria.CriteriaBuilderImpl;
import org.apache.openjpa.persistence.criteria.CriteriaDeleteImpl;
import org.apache.openjpa.persistence.criteria.CriteriaUpdateImpl;
@@ -122,6 +126,7 @@ 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 = false;
private transient Log _log;
public EntityManagerImpl() {
@@ -564,11 +569,18 @@ public class EntityManagerImpl
return this;
}
+ /**
+ * Joins a transaction, if availble.
+ */
public void joinTransaction() {
assertNotCloseInvoked();
- if (!_broker.syncWithManagedTransaction())
+
+ if (!_broker.syncWithManagedTransaction()) {
throw new TransactionRequiredException(_loc.get
("no-managed-trans"), null, null, false);
+ } else {
+ _isJoinedToTransaction = true;
+ }
}
public void begin() {
@@ -1032,8 +1044,7 @@ public class EntityManagerImpl
_broker.assertOpen();
try {
QueryMetaData meta = _broker.getConfiguration().
- getMetaDataRepositoryInstance().getQueryMetaData(null, name,
- _broker.getClassLoader(), true);
+ getMetaDataRepositoryInstance().getQueryMetaData(null, name, _broker.getClassLoader(), true);
String qid = meta.getQueryString();
PreparedQuery pq = JPQLParser.LANG_JPQL.equals(meta.getLanguage()) ? getPreparedQuery(qid) : null;
@@ -1059,26 +1070,57 @@ public class EntityManagerImpl
}
}
+ /**
+ * Creates a SQL query from the given string.
+ *
+ * @param sql can be a proper SQL statement, or simply a stored procedure name
+ */
public OpenJPAQuery createNativeQuery(String query) {
validateSQL(query);
return createQuery(QueryLanguages.LANG_SQL, query);
}
+ /**
+ * Creates a SQL query from the given string.
+ *
+ * @param sql can be a proper SQL statement, or simply a stored procedure name
+ * @param cls the type of expected result.
+ */
public OpenJPAQuery createNativeQuery(String query, Class cls) {
return createNativeQuery(query).setResultClass(cls);
}
+ /**
+ * Creates a SQL query from the given string.
+ *
+ * @param sql can be a proper SQL statement, or simply a stored procedure name
+ * @param mappingName name of the mapping used to convert the results into memory
+ */
public OpenJPAQuery createNativeQuery(String query, String mappingName) {
assertNotCloseInvoked();
validateSQL(query);
- org.apache.openjpa.kernel.Query kernelQuery = _broker.newQuery(
- QueryLanguages.LANG_SQL, query);
+ org.apache.openjpa.kernel.Query kernelQuery = _broker.newQuery(QueryLanguages.LANG_SQL, query);
kernelQuery.setResultMapping(null, mappingName);
return newQueryImpl(kernelQuery, null, _log);
}
- protected <T> QueryImpl<T> newQueryImpl(org.apache.openjpa.kernel.Query kernelQuery,
- QueryMetaData qmd, Log log) {
+ /**
+ * Creates a facade version of a query from the given kerenl query and metadata.
+ * @param <T> type of expected result
+ * @param kernelQuery
+ * @param qmd
+ * @param log supply a logger
+ * @return
+ */
+ protected <T> QueryImpl<T> newQueryImpl(org.apache.openjpa.kernel.Query kernelQuery, QueryMetaData qmd, Log log) {
+ return new QueryImpl<T>(this, _ret, kernelQuery, qmd, log);
+ }
+
+ /**
+ * Same as {@linkplain #newQueryImpl(org.apache.openjpa.kernel.Query, QueryMetaData, Log)}} except
+ * a default logger is supplied.
+ */
+ protected <T> QueryImpl<T> newQueryImpl(org.apache.openjpa.kernel.Query kernelQuery, QueryMetaData qmd) {
return new QueryImpl<T>(this, _ret, kernelQuery, qmd, _log);
}
@@ -1090,11 +1132,11 @@ public class EntityManagerImpl
* query creation
*/
protected <T> QueryImpl<T> newQueryImpl(org.apache.openjpa.kernel.Query kernelQuery) {
- return new QueryImpl<T>(this, _ret, kernelQuery, null);
+ return new QueryImpl<T>(this, _ret, kernelQuery, _log);
}
/**
- * Validate that the user provided SQL.
+ * Validate that the user provided SQL or simply a name of a stored procedure.
*/
protected void validateSQL(String query) {
if (StringUtils.trimToNull(query) == null)
@@ -1925,34 +1967,108 @@ public class EntityManagerImpl
return facadeQuery;
}
+ /**
+ * Creates a Query that can be executed as a Stored Procedure.
+ * <br>
+ * The details about the Stored Procedure is specified in a {@link NamedStoredProcedureQuery} annotation
+ * or its equivalent XML descriptor. The input argument is the name attribute of that annotation.
+ * <br>
+ * Construction of a {@link StoredProcedureQuery} object is a three step process
+ * <LI>a corresponding SQL {@code S} (e.g. {@code "call <procedure>(?,?...)"}) is formed.
+ * The number of parameter argument in the {@coe call} statement
+ * is deternmined by the parameters declared in {@link NamedStoredProcedureQuery#parameters()} annotation.
+ * <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>
+ * A {@link NamedStoredProcedureQuery named Stored Procedure Query} also may specify how its results be mapped.
+ * A {@link QueryResultMapping query result mapping} is implicitly associated. It is implicit as opposed to
+ * other {@link QueryResultMapping} mapping instances that are created via {@link SqlResultSetMapping}
+ * annotation which has an explicit name. The name of the implicit mapping is always
+ * {@code <name>.ResultSetMapping}.
+ *
+ */
@Override
public StoredProcedureQuery createNamedStoredProcedureQuery(String name) {
// TODO JPA 2.1 Method
- return null;
+ QueryMetaData meta = getQueryMetadata(name);
+ if (meta instanceof MultiQueryMetaData) {
+ throw new RuntimeException(name + " is not a Stored Procedure Query");
+ }
+ String procedureName = meta.getQueryString();
+ int parameterCount = ((MultiQueryMetaData)meta).getParameterCount();
+ StringBuilder sql = new StringBuilder("call ").append(procedureName).append("(");
+ for (int i = 0; i < parameterCount; i++) {
+ sql.append("?");
+ if (i < parameterCount-1) sql.append(",");
+ }
+ sql.append(")");
+ return sp(sql.toString(), (MultiQueryMetaData)meta, name + ".ResultSetMapping");
+// org.apache.openjpa.kernel.Query kernelQuery = _broker.newQuery(QueryLanguages.LANG_SQL, sql.toString());
+// kernelQuery.setResultMapping(null, name + ".ResultSetMapping");
+// org.apache.openjpa.persistence.QueryImpl<?> facadeQuery = new QueryImpl(this, _ret, kernelQuery, meta, _log);
+//
+// return new StoredProcedureQueryImpl(facadeQuery);
}
+ /**
+ * Creates a Stored Procedure Query directly from the name of the database procedure.
+ * This method follows three similiar steps as in {@link #createNamedStoredProcedureQuery(String)}
+ * but with some critical difference.
+ * <br>The major difference in this case from creating a query by its logical name is lack of metadata
+ * at the time of creation. It is not known at this point how many arguments are required by the
+ * procedure or how its results be mapped.
+ * <br>
+ * <LI>So the name of the procedure itself is treated as a query string (which is not a valid SQL}.
+ * <LI>No result set mapping name is associated with the kernel query.
+ *
+ */
@Override
public StoredProcedureQuery createStoredProcedureQuery(String procedureName) {
// TODO JPA 2.1 Method
- return null;
+
+ org.apache.openjpa.kernel.Query kernelQuery = _broker.newQuery(QueryLanguages.LANG_STORED_PROC,
+ procedureName);
+ org.apache.openjpa.persistence.QueryImpl<?> facadeQuery = new QueryImpl(this, _ret,
+ kernelQuery, null, _log);
+ return new StoredProcedureQueryImpl(procedureName, facadeQuery);
}
@Override
public StoredProcedureQuery createStoredProcedureQuery(String procedureName, Class... resultClasses) {
// TODO JPA 2.1 Method
- return null;
+ String tempName = "Temp"+System.currentTimeMillis();
+ MultiQueryMetaData meta = new MultiQueryMetaData(null, "xyz");
+ for (Class res : resultClasses) {
+ meta.addComponent().setResultType(res);
+ }
+ return sp(procedureName, meta, tempName);
}
@Override
public StoredProcedureQuery createStoredProcedureQuery(String procedureName, String... resultSetMappings) {
// TODO JPA 2.1 Method
- return null;
+ String tempName = "Temp"+System.currentTimeMillis();
+ MultiQueryMetaData meta = new MultiQueryMetaData(null, "xyz");
+ for (String mapping : resultSetMappings) {
+ meta.addComponent().setResultSetMappingName(mapping);
+ }
+ return sp(procedureName, meta, tempName);
+ }
+
+ private StoredProcedureQuery sp(String sql, MultiQueryMetaData meta, String mappingName) {
+ org.apache.openjpa.kernel.Query kernelQuery = _broker.newQuery(QueryLanguages.LANG_STORED_PROC, sql);
+ kernelQuery.setResultMapping(null, mappingName);
+ org.apache.openjpa.persistence.QueryImpl<?> facadeQuery = new QueryImpl(this, _ret, kernelQuery, meta, _log);
+ return new StoredProcedureQueryImpl(sql, facadeQuery);
}
@Override
public boolean isJoinedToTransaction() {
// TODO JPA 2.1 Method
- return false;
+ return isActive() && _isJoinedToTransaction;
}
@Override
@@ -1978,4 +2094,20 @@ public class EntityManagerImpl
// TODO JPA 2.1 Method
return null;
}
+
+ /**
+ * Gets the metadat associated with the given name.
+ * @param name logical name in which a query has been registered.
+ * @return the metadata associated with the named query
+ * @throws UserException if no query has been registered with the given name.
+ */
+ 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 stored procedure query named [" + name + "]");
+ }
+ return meta;
+ }
+
}
Modified: openjpa/sandboxes/21/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/FetchPlan.java
URL: http://svn.apache.org/viewvc/openjpa/sandboxes/21/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/FetchPlan.java?rev=1480473&r1=1480472&r2=1480473&view=diff
==============================================================================
--- openjpa/sandboxes/21/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/FetchPlan.java (original)
+++ openjpa/sandboxes/21/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/FetchPlan.java Wed May 8 21:38:29 2013
@@ -21,6 +21,7 @@ package org.apache.openjpa.persistence;
import java.util.Collection;
import java.util.Map;
+import javax.persistence.EntityGraph;
import javax.persistence.LockModeType;
import javax.persistence.PessimisticLockScope;
Modified: openjpa/sandboxes/21/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/MetaDataTag.java
URL: http://svn.apache.org/viewvc/openjpa/sandboxes/21/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/MetaDataTag.java?rev=1480473&r1=1480472&r2=1480473&view=diff
==============================================================================
--- openjpa/sandboxes/21/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/MetaDataTag.java (original)
+++ openjpa/sandboxes/21/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/MetaDataTag.java Wed May 8 21:38:29 2013
@@ -30,6 +30,10 @@ package org.apache.openjpa.persistence;
* @nojavadoc
*/
public enum MetaDataTag {
+ // Position for these need to be determined
+ CONVERTER,
+ CONVERT,
+ CONVERTS,
// sorted by XML order
ACCESS,
CACHEABLE,
Modified: openjpa/sandboxes/21/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/PersistenceMetaDataFactory.java
URL: http://svn.apache.org/viewvc/openjpa/sandboxes/21/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/PersistenceMetaDataFactory.java?rev=1480473&r1=1480472&r2=1480473&view=diff
==============================================================================
--- openjpa/sandboxes/21/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/PersistenceMetaDataFactory.java (original)
+++ openjpa/sandboxes/21/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/PersistenceMetaDataFactory.java Wed May 8 21:38:29 2013
@@ -20,6 +20,7 @@ package org.apache.openjpa.persistence;
import java.io.File;
import java.io.IOException;
+import java.lang.annotation.Annotation;
import java.net.URL;
import java.security.AccessController;
import java.util.ArrayList;
@@ -39,6 +40,8 @@ import javax.persistence.NamedNativeQuer
import javax.persistence.NamedNativeQuery;
import javax.persistence.NamedQueries;
import javax.persistence.NamedQuery;
+import javax.persistence.NamedStoredProcedureQueries;
+import javax.persistence.NamedStoredProcedureQuery;
import javax.persistence.SqlResultSetMapping;
import javax.persistence.SqlResultSetMappings;
import javax.persistence.metamodel.StaticMetamodel;
@@ -349,32 +352,37 @@ public class PersistenceMetaDataFactory
return null;
Collection<Class<?>> classes = repos.loadPersistentTypes(false, loader);
for (Class<?> cls : classes) {
- if ((AccessController.doPrivileged(J2DoPrivHelper
- .isAnnotationPresentAction(cls, NamedQuery.class)))
- .booleanValue() && hasNamedQuery
- (queryName, (NamedQuery) cls.getAnnotation(NamedQuery.class)))
+ if (isAnnotated(cls, NamedQuery.class)
+ && hasNamedQuery(queryName, cls.getAnnotation(NamedQuery.class)))
return cls;
- if ((AccessController.doPrivileged(J2DoPrivHelper
- .isAnnotationPresentAction(cls, NamedQueries.class)))
- .booleanValue() &&
- hasNamedQuery(queryName, ((NamedQueries) cls.
- getAnnotation(NamedQueries.class)).value()))
+ if (isAnnotated(cls, NamedQueries.class)
+ && hasNamedQuery(queryName, cls.getAnnotation(NamedQueries.class).value()))
return cls;
- if ((AccessController.doPrivileged(J2DoPrivHelper
- .isAnnotationPresentAction(cls, NamedNativeQuery.class)))
- .booleanValue() &&
- hasNamedNativeQuery(queryName, (NamedNativeQuery) cls.
- getAnnotation(NamedNativeQuery.class)))
+ if (isAnnotated(cls, NamedNativeQuery.class)
+ && hasNamedNativeQuery(queryName, cls.getAnnotation(NamedNativeQuery.class)))
return cls;
- if ((AccessController.doPrivileged(J2DoPrivHelper
- .isAnnotationPresentAction(cls, NamedNativeQueries.class)))
- .booleanValue() &&
- hasNamedNativeQuery(queryName, ((NamedNativeQueries) cls.
- getAnnotation(NamedNativeQueries.class)).value()))
+ if (isAnnotated(cls, NamedNativeQueries.class)
+ && hasNamedNativeQuery(queryName, 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;
}
+
+ /**
+ * Affirms if the given class is annotated with the given annotation.
+ * @param cls
+ * @param annotationClazz
+ * @return
+ */
+ private boolean isAnnotated(Class<?> cls, Class<? extends Annotation> annotationClazz) {
+ return AccessController.doPrivileged(J2DoPrivHelper.isAnnotationPresentAction(cls, annotationClazz));
+ }
@Override
public Class<?> getResultSetMappingScope(String rsMappingName,
@@ -427,6 +435,15 @@ 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;
+ }
+
@Override
protected MetaDataFilter newMetaDataFilter() {
Added: openjpa/sandboxes/21/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/StoredProcedureQueryImpl.java
URL: http://svn.apache.org/viewvc/openjpa/sandboxes/21/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/StoredProcedureQueryImpl.java?rev=1480473&view=auto
==============================================================================
--- openjpa/sandboxes/21/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/StoredProcedureQueryImpl.java (added)
+++ openjpa/sandboxes/21/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/StoredProcedureQueryImpl.java Wed May 8 21:38:29 2013
@@ -0,0 +1,342 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.openjpa.persistence;
+
+import java.util.Calendar;
+import java.util.Date;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+import javax.persistence.FlushModeType;
+import javax.persistence.LockModeType;
+import javax.persistence.Parameter;
+import javax.persistence.ParameterMode;
+import javax.persistence.StoredProcedureQuery;
+import javax.persistence.TemporalType;
+
+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.util.RuntimeExceptionTranslator;
+import org.apache.openjpa.util.UserException;
+
+/**
+ * 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 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
+ *
+ */
+public class StoredProcedureQueryImpl<X> implements StoredProcedureQuery {
+ final String _name;
+ final AbstractQuery<?> _delegate;
+ QueryResultCallback _callback;
+
+ public StoredProcedureQueryImpl(String name, AbstractQuery<?> delegate) {
+ _name = name;
+ _delegate = delegate;
+ _delegate.compile();
+ }
+
+ public OpenJPAQuery<?> getDelegate() {
+ return _delegate;
+ }
+
+ @Override
+ public boolean execute() {
+ if (_callback == null) {
+ _callback = (QueryResultCallback)((QueryImpl<?>)_delegate).getDelegate()
+ .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 RuntimeException(ex);
+ }
+ }
+
+ @Override
+ public Object getSingleResult() {
+ // TODO JPA 2.1 Method
+ return _delegate.getSingleResult();
+ }
+
+ @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) {
+ // TODO JPA 2.1 Method
+ _delegate.setParameter(param, value);
+ return this;
+ }
+
+ @Override
+ public StoredProcedureQuery setParameter(Parameter<Calendar> param, Calendar cal, TemporalType temporalType) {
+ // TODO JPA 2.1 Method
+ _delegate.setParameter(param, cal, temporalType);
+ return this;
+ }
+
+ @Override
+ public StoredProcedureQuery setParameter(Parameter<Date> param, Date value, TemporalType temporalType) {
+ // TODO JPA 2.1 Method
+ _delegate.setParameter(param, value, temporalType);
+ return this;
+ }
+
+ @Override
+ public StoredProcedureQuery registerStoredProcedureParameter(int position, Class type, ParameterMode mode) {
+ // TODO JPA 2.1 Method
+ ParameterImpl param = new ParameterImpl(position, type);
+ _delegate.declareParameter(position, param);
+ return this;
+ }
+
+ @Override
+ public StoredProcedureQuery registerStoredProcedureParameter(String name, Class type, ParameterMode mode) {
+ // TODO JPA 2.1 Method
+ ParameterImpl param = new ParameterImpl(name, type);
+ _delegate.declareParameter(name, param);
+ return this;
+ }
+
+ @Override
+ public Object getOutputParameterValue(int position) {
+ // TODO JPA 2.1 Method
+ return _delegate.getParameterValue(position);
+ }
+
+ @Override
+ public Object getOutputParameterValue(String parameterName) {
+ // TODO JPA 2.1 Method
+ return _delegate.getParameterValue(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() {
+ // TODO JPA 2.1 Method
+ return _delegate.getParameters();
+ }
+
+ @Override
+ public Parameter<?> getParameter(String name) {
+ // TODO JPA 2.1 Method
+ return _delegate.getParameter(name);
+ }
+
+ @Override
+ public Parameter<?> getParameter(int position) {
+ // TODO JPA 2.1 Method
+ return _delegate.getParameter(position);
+ }
+
+ @Override
+ public Object getParameterValue(String name) {
+ // TODO JPA 2.1 Method
+ return _delegate.getParameterValue(name);
+ }
+
+ @Override
+ public Object getParameterValue(int position) {
+ // TODO JPA 2.1 Method
+ 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) {
+ // TODO JPA 2.1 Method
+ _delegate.setHint(hintName, value);
+ return this;
+ }
+
+ @Override
+ public StoredProcedureQuery setParameter(String name, Object value) {
+ // TODO JPA 2.1 Method
+ _delegate.setParameter(name, value);
+ return this;
+ }
+
+ @Override
+ public StoredProcedureQuery setParameter(String name, Calendar cal, TemporalType temporalType) {
+ // TODO JPA 2.1 Method
+ _delegate.setParameter(name, cal, temporalType);
+ return this;
+ }
+
+ @Override
+ public StoredProcedureQuery setParameter(String name, Date date, TemporalType temporalType) {
+ // TODO JPA 2.1 Method
+ _delegate.setParameter(name, date, temporalType);
+ return this;
+ }
+
+ @Override
+ public StoredProcedureQuery setParameter(int position, Object value) {
+ // TODO JPA 2.1 Method
+ _delegate.setParameter(position, value);
+ return this;
+ }
+
+ @Override
+ public StoredProcedureQuery setParameter(int position, Calendar value, TemporalType temporalType) {
+ // TODO JPA 2.1 Method
+ _delegate.setParameter(position, value, temporalType);
+ return this;
+ }
+
+ @Override
+ public StoredProcedureQuery setParameter(int position, Date value, TemporalType temporalType) {
+ // TODO JPA 2.1 Method
+ _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");
+ }
+ }
+
+ public String toString() {
+ return _name;
+ }
+
+}
Propchange: openjpa/sandboxes/21/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/StoredProcedureQueryImpl.java
------------------------------------------------------------------------------
svn:eol-style = native
Modified: openjpa/sandboxes/21/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/XMLPersistenceMetaDataParser.java
URL: http://svn.apache.org/viewvc/openjpa/sandboxes/21/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/XMLPersistenceMetaDataParser.java?rev=1480473&r1=1480472&r2=1480473&view=diff
==============================================================================
--- openjpa/sandboxes/21/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/XMLPersistenceMetaDataParser.java (original)
+++ openjpa/sandboxes/21/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/XMLPersistenceMetaDataParser.java Wed May 8 21:38:29 2013
@@ -79,6 +79,7 @@ import static org.apache.openjpa.persist
import org.apache.openjpa.util.ImplHelper;
import org.apache.openjpa.util.InternalException;
import org.apache.openjpa.util.MetaDataException;
+import org.apache.openjpa.util.UserException;
import org.xml.sax.Attributes;
import org.xml.sax.Locator;
import org.xml.sax.SAXException;
@@ -121,8 +122,7 @@ public class XMLPersistenceMetaDataParse
SEQUENCE_GEN_SCHEMA
}
- private static final Map<String, Object> _elems =
- new HashMap<String, Object>();
+ private static final Map<String, Object> _elems = new HashMap<String, Object>();
// Map for storing deferred metadata which needs to be populated
// after embeddables are loaded.
@@ -1830,19 +1830,8 @@ public class XMLPersistenceMetaDataParse
if (log.isTraceEnabled())
log.trace(_loc.get("parse-query", name));
- QueryMetaData meta = getRepository().searchQueryMetaDataByName(name);
- if (meta != null) {
- Class<?> defType = meta.getDefiningType();
- if ((defType != _cls) && log.isWarnEnabled()) {
- log.warn(_loc.get("dup-query", name, currentLocation(),
- defType));
- }
- pushElement(meta);
- return true;
- }
+ QueryMetaData meta = new QueryMetaData(_cls, name);
- meta = getRepository().addQueryMetaData(null, name);
- meta.setDefiningType(_cls);
meta.setLanguage(JPQLParser.LANG_JPQL);
meta.setQueryString(attrs.getValue("query"));
String lockModeStr = attrs.getValue("lock-mode");
@@ -1865,11 +1854,28 @@ public class XMLPersistenceMetaDataParse
meta.setSourceMode(MODE_MAPPING);
else
meta.setSourceMode(MODE_QUERY);
+
+ addQueryMetaData(cur, meta);
pushElement(meta);
return true;
}
/**
+ * Adds the given query meta.
+ * @param meta a query meta data
+ * @exception throws exception if a query meta data with the same name of the given meta
+ * already exists in the repository.
+ */
+ protected void addQueryMetaData(Object location, QueryMetaData meta) {
+ QueryMetaData existing = getRepository().addQueryMetaData(meta);
+ if (existing != null) {
+ Class<?> scope = existing.getDefiningType();
+ throw new UserException(_loc.get("dup-query", meta.getName(), location, scope));
+ }
+ }
+
+
+ /**
* A private worker method that calculates the lock mode for an individual NamedQuery. If the NamedQuery is
* configured to use the NONE lock mode(explicit or implicit), this method will promote the lock to a READ
* level lock. This was done to allow for JPA1 apps to function properly under a 2.0 runtime.
@@ -1945,8 +1951,8 @@ public class XMLPersistenceMetaDataParse
log.warn(_loc.get("override-query", name, currentLocation()));
}
- meta = getRepository().addQueryMetaData(null, name);
- meta.setDefiningType(_cls);
+ meta = new QueryMetaData(_cls, name);
+ getRepository().addQueryMetaData(meta);
meta.setLanguage(QueryLanguages.LANG_SQL);
meta.setQueryString(attrs.getValue("query"));
String val = attrs.getValue("result-class");