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");