[hibernate-commits] Hibernate SVN: r19219 - in core/trunk/entitymanager/src: test/java/org/hibernate/ejb/test and 1 other directories.

hibernate-commits at lists.jboss.org hibernate-commits at lists.jboss.org
Tue Apr 13 09:35:39 EDT 2010


Author: epbernard
Date: 2010-04-13 09:35:38 -0400 (Tue, 13 Apr 2010)
New Revision: 19219

Modified:
   core/trunk/entitymanager/src/main/java/org/hibernate/ejb/AbstractEntityManagerImpl.java
   core/trunk/entitymanager/src/test/java/org/hibernate/ejb/test/Item.java
   core/trunk/entitymanager/src/test/java/org/hibernate/ejb/test/query/QueryTest.java
Log:
HHH-5106 add support for SQL Named Typed-Query

Modified: core/trunk/entitymanager/src/main/java/org/hibernate/ejb/AbstractEntityManagerImpl.java
===================================================================
--- core/trunk/entitymanager/src/main/java/org/hibernate/ejb/AbstractEntityManagerImpl.java	2010-04-13 08:51:33 UTC (rev 19218)
+++ core/trunk/entitymanager/src/main/java/org/hibernate/ejb/AbstractEntityManagerImpl.java	2010-04-13 13:35:38 UTC (rev 19219)
@@ -93,12 +93,17 @@
 import org.hibernate.ejb.util.CacheModeHelper;
 import org.hibernate.ejb.util.ConfigurationHelper;
 import org.hibernate.ejb.util.LockModeTypeHelper;
+import org.hibernate.engine.NamedSQLQueryDefinition;
+import org.hibernate.engine.ResultSetMappingDefinition;
 import org.hibernate.engine.SessionFactoryImplementor;
 import org.hibernate.engine.SessionImplementor;
+import org.hibernate.engine.query.sql.NativeSQLQueryReturn;
+import org.hibernate.engine.query.sql.NativeSQLQueryRootReturn;
 import org.hibernate.proxy.HibernateProxy;
 import org.hibernate.transaction.TransactionFactory;
 import org.hibernate.transform.BasicTransformerAdapter;
 import org.hibernate.util.JTAHelper;
+import org.hibernate.util.ReflectHelper;
 
 /**
  * @author <a href="mailto:gavin at hibernate.org">Gavin King</a>
@@ -449,18 +454,60 @@
 
 	public <T> TypedQuery<T> createNamedQuery(String name, Class<T> resultClass) {
 		try {
+			/*
+			 * Get the named query.
+			 * If the named query is a SQL query, get the expected returned type from the query definition
+			 * or its associated result set mapping
+			 * If the named query is a HQL query, use getReturnType()
+			 */
 			org.hibernate.Query namedQuery = getSession().getNamedQuery( name );
+			//TODO clean this up to avoid downcasting
+			final SessionFactoryImplementor factoryImplementor = ( SessionFactoryImplementor ) entityManagerFactory.getSessionFactory();
+			final NamedSQLQueryDefinition queryDefinition = factoryImplementor.getNamedSQLQuery( name );
 			try {
-				if ( namedQuery.getReturnTypes().length != 1 ) {
-					throw new IllegalArgumentException( "Cannot create TypedQuery for query with more than one return" );
+				if ( queryDefinition != null ) {
+					Class<?> actualReturnedClass;
+
+					final NativeSQLQueryReturn[] queryReturns;
+					if ( queryDefinition.getQueryReturns() != null ) {
+						queryReturns = queryDefinition.getQueryReturns();
+					}
+					else if ( queryDefinition.getResultSetRef() != null ) {
+						final ResultSetMappingDefinition rsMapping = factoryImplementor.getResultSetMapping(
+								queryDefinition.getResultSetRef()
+						);
+						queryReturns = rsMapping.getQueryReturns();
+					}
+					else {
+						throw new AssertionFailure( "Unsupported named query model. Please report the bug in Hibernate EntityManager");
+					}
+					if ( queryReturns.length > 1 ) {
+						throw new IllegalArgumentException( "Cannot create TypedQuery for query with more than one return" );
+					}
+					final NativeSQLQueryReturn nativeSQLQueryReturn = queryReturns[0];
+					if ( nativeSQLQueryReturn instanceof NativeSQLQueryRootReturn ) {
+						final String entityClassName = ( ( NativeSQLQueryRootReturn ) nativeSQLQueryReturn ).getReturnEntityName();
+						try {
+							actualReturnedClass = ReflectHelper.classForName( entityClassName, AbstractEntityManagerImpl.class );
+						}
+						catch ( ClassNotFoundException e ) {
+							throw new AssertionFailure( "Unable to instantiate class declared on named native query: " + name + " " + entityClassName );
+						}
+						if ( !resultClass.isAssignableFrom( actualReturnedClass ) ) {
+							throw buildIncompatibleException( resultClass, actualReturnedClass );
+						}
+					}
+					else {
+						//TODO support other NativeSQLQueryReturn type. For now let it go.
+					}
 				}
-				if ( !resultClass.isAssignableFrom( namedQuery.getReturnTypes()[0].getReturnedClass() ) ) {
-					throw new IllegalArgumentException(
-							"Type specified for TypedQuery [" +
-									resultClass.getName() +
-									"] is incompatible with query return type [" +
-									namedQuery.getReturnTypes()[0].getReturnedClass() + "]"
-					);
+				else {
+					if ( namedQuery.getReturnTypes().length != 1 ) {
+						throw new IllegalArgumentException( "Cannot create TypedQuery for query with more than one return" );
+					}
+					if ( !resultClass.isAssignableFrom( namedQuery.getReturnTypes()[0].getReturnedClass() ) ) {
+						throw buildIncompatibleException( resultClass, namedQuery.getReturnTypes()[0].getReturnedClass() );
+					}
 				}
 				return new QueryImpl<T>( namedQuery, this );
 			}
@@ -473,6 +520,15 @@
 		}
 	}
 
+	private IllegalArgumentException buildIncompatibleException(Class<?> resultClass, Class<?> actualResultClass) {
+		return new IllegalArgumentException(
+							"Type specified for TypedQuery [" +
+									resultClass.getName() +
+									"] is incompatible with query return type [" +
+									actualResultClass + "]"
+					);
+	}
+
 	public Query createNativeQuery(String sqlString) {
 		try {
 			SQLQuery q = getSession().createSQLQuery( sqlString );

Modified: core/trunk/entitymanager/src/test/java/org/hibernate/ejb/test/Item.java
===================================================================
--- core/trunk/entitymanager/src/test/java/org/hibernate/ejb/test/Item.java	2010-04-13 08:51:33 UTC (rev 19218)
+++ core/trunk/entitymanager/src/test/java/org/hibernate/ejb/test/Item.java	2010-04-13 13:35:38 UTC (rev 19219)
@@ -9,6 +9,9 @@
 import javax.persistence.EntityResult;
 import javax.persistence.FieldResult;
 import javax.persistence.Id;
+import javax.persistence.NamedNativeQueries;
+import javax.persistence.NamedNativeQuery;
+import javax.persistence.NamedQuery;
 import javax.persistence.OneToMany;
 import javax.persistence.SqlResultSetMapping;
 
@@ -16,12 +19,24 @@
  * @author Gavin King
  */
 @Entity(name = "Item")
- at SqlResultSetMapping(name = "getItem", entities =
- at EntityResult(entityClass = org.hibernate.ejb.test.Item.class, fields = {
- at FieldResult(name = "name", column = "itemname"),
- at FieldResult(name = "descr", column = "itemdescription")
-		})
+	@SqlResultSetMapping(name = "getItem", entities =
+		@EntityResult(entityClass = org.hibernate.ejb.test.Item.class, fields = {
+			@FieldResult(name = "name", column = "itemname"),
+			@FieldResult(name = "descr", column = "itemdescription")
+			})
 )
+ at NamedNativeQueries({
+		@NamedNativeQuery(
+				name = "nativeItem1",
+				query = "select name as itemname, descr as itemdescription from Item",
+				resultSetMapping = "getItem"
+		),
+		@NamedNativeQuery(
+				name = "nativeItem2",
+				query = "select * from Item",
+				resultClass = Item.class
+		)
+})
 //@Cache(region="Item", usage=NONSTRICT_READ_WRITE)
 public class Item implements Serializable {
 

Modified: core/trunk/entitymanager/src/test/java/org/hibernate/ejb/test/query/QueryTest.java
===================================================================
--- core/trunk/entitymanager/src/test/java/org/hibernate/ejb/test/query/QueryTest.java	2010-04-13 08:51:33 UTC (rev 19218)
+++ core/trunk/entitymanager/src/test/java/org/hibernate/ejb/test/query/QueryTest.java	2010-04-13 13:35:38 UTC (rev 19219)
@@ -435,6 +435,26 @@
 
 	}
 
+	public void testTypedNamedNativeQuery() {
+		Item item = new Item( "Mouse", "Micro$oft mouse" );
+
+		EntityManager em = getOrCreateEntityManager();
+		em.getTransaction().begin();
+		em.persist( item );
+		assertTrue( em.contains( item ) );
+		em.getTransaction().commit();
+
+		em.getTransaction().begin();
+		item = em.createNamedQuery( "nativeItem1", Item.class ).getSingleResult();
+		item = em.createNamedQuery( "nativeItem2", Item.class ).getSingleResult();
+		assertNotNull( item );
+		assertEquals( "Micro$oft mouse", item.getDescr() );
+		em.remove( item );
+		em.getTransaction().commit();
+
+		em.close();
+	}
+
 	public Class[] getAnnotatedClasses() {
 		return new Class[]{
 				Item.class,



More information about the hibernate-commits mailing list