[hibernate-commits] Hibernate SVN: r17426 - in core/trunk: entitymanager/src/main/java/org/hibernate/ejb and 1 other directory.

hibernate-commits at lists.jboss.org hibernate-commits at lists.jboss.org
Wed Aug 26 16:34:59 EDT 2009


Author: steve.ebersole at jboss.com
Date: 2009-08-26 16:34:58 -0400 (Wed, 26 Aug 2009)
New Revision: 17426

Added:
   core/trunk/entitymanager/src/main/java/org/hibernate/ejb/AbstractQueryImpl.java
   core/trunk/entitymanager/src/main/java/org/hibernate/ejb/QueryHints.java
Modified:
   core/trunk/core/src/main/java/org/hibernate/impl/AbstractQueryImpl.java
   core/trunk/entitymanager/src/main/java/org/hibernate/ejb/AbstractEntityManagerImpl.java
   core/trunk/entitymanager/src/main/java/org/hibernate/ejb/HibernateEntityManagerImplementor.java
   core/trunk/entitymanager/src/main/java/org/hibernate/ejb/HibernatePersistence.java
   core/trunk/entitymanager/src/main/java/org/hibernate/ejb/HibernateQuery.java
   core/trunk/entitymanager/src/main/java/org/hibernate/ejb/QueryImpl.java
Log:
EJB-461 - Implement JPA 2.0 criteria apis (compiling)


Modified: core/trunk/core/src/main/java/org/hibernate/impl/AbstractQueryImpl.java
===================================================================
--- core/trunk/core/src/main/java/org/hibernate/impl/AbstractQueryImpl.java	2009-08-26 14:40:41 UTC (rev 17425)
+++ core/trunk/core/src/main/java/org/hibernate/impl/AbstractQueryImpl.java	2009-08-26 20:34:58 UTC (rev 17426)
@@ -116,6 +116,10 @@
 		this.parameterMetadata = parameterMetadata;
 	}
 
+	public ParameterMetadata getParameterMetadata() {
+		return parameterMetadata;
+	}
+
 	public String toString() {
 		return StringHelper.unqualify( getClass().getName() ) + '(' + queryString + ')';
 	}
@@ -161,7 +165,13 @@
 	}
 
 	public Query setMaxResults(int maxResults) {
-		selection.setMaxRows( new Integer(maxResults) );
+		if ( maxResults < 0 ) {
+			// treat negatives specically as meaning no limit...
+			selection.setMaxRows( null );
+		}
+		else {
+			selection.setMaxRows( new Integer(maxResults) );
+		}
 		return this;
 	}
 

Modified: core/trunk/entitymanager/src/main/java/org/hibernate/ejb/AbstractEntityManagerImpl.java
===================================================================
--- core/trunk/entitymanager/src/main/java/org/hibernate/ejb/AbstractEntityManagerImpl.java	2009-08-26 14:40:41 UTC (rev 17425)
+++ core/trunk/entitymanager/src/main/java/org/hibernate/ejb/AbstractEntityManagerImpl.java	2009-08-26 20:34:58 UTC (rev 17426)
@@ -1,9 +1,11 @@
 /*
- * Copyright (c) 2009, Red Hat Middleware LLC or third-party contributors as
- * indicated by the @author tags or express copyright attribution
- * statements applied by the authors.  All third-party contributions are
- * distributed under license by Red Hat Middleware LLC.
+ * Hibernate, Relational Persistence for Idiomatic Java
  *
+ * Copyright (c) 2009 by Red Hat Inc and/or its affiliates or by
+ * third-party contributors as indicated by either @author tags or express
+ * copyright attribution statements applied by the authors.  All
+ * third-party contributions are distributed under license by Red Hat Inc.
+ *
  * This copyrighted material is made available to anyone wishing to use, modify,
  * copy, or redistribute it subject to the terms and conditions of the GNU
  * Lesser General Public License, as published by the Free Software Foundation.
@@ -80,6 +82,7 @@
 /**
  * @author <a href="mailto:gavin at hibernate.org">Gavin King</a>
  * @author Emmanuel Bernard
+ * @author Steve Ebersole
  */
 @SuppressWarnings("unchecked")
 public abstract class AbstractEntityManagerImpl implements HibernateEntityManagerImplementor, Serializable {
@@ -115,19 +118,34 @@
 		this.properties = null;
 	}
 
-	public Query createQuery(String ejbqlString) {
-		//adjustFlushMode();
+	public Query createQuery(String jpaqlString) {
 		try {
-			return new QueryImpl( getSession().createQuery( ejbqlString ), this );
+			return new QueryImpl<Object>( getSession().createQuery( jpaqlString ), this );
 		}
 		catch ( HibernateException he ) {
-			throwPersistenceException( he );
-			return null;
+			throw convert( he );
 		}
 	}
 
-	public <T> TypedQuery<T> createQuery(String qlString, Class<T> resultClass) {
-		throw new UnsupportedOperationException( "Not yet implemented" );
+	public <T> TypedQuery<T> createQuery(String jpaqlString, Class<T> resultClass) {
+		try {
+			org.hibernate.Query hqlQuery = getSession().createQuery( jpaqlString );
+			if ( hqlQuery.getReturnTypes().length != 1 ) {
+				throw new IllegalArgumentException( "Cannot create TypedQuery for query with more than one return" );
+			}
+			if ( ! resultClass.isAssignableFrom( hqlQuery.getReturnTypes()[0].getReturnedClass() ) ) {
+				throw new IllegalArgumentException(
+						"Type specified for TypedQuery [" +
+								resultClass.getName() +
+								"] is incompatible with query return type [" +
+								hqlQuery.getReturnTypes()[0].getReturnedClass() + "]"
+				);
+			}
+			return new QueryImpl<T>( hqlQuery, this );
+		}
+		catch ( HibernateException he ) {
+			throw convert( he );
+		}
 	}
 
 	public <T> TypedQuery<T> createQuery(CriteriaQuery<T> criteriaQuery) {
@@ -165,69 +183,81 @@
 	}
 
 	public Query createNamedQuery(String name) {
-		//adjustFlushMode();
-		org.hibernate.Query namedQuery;
 		try {
-			namedQuery = getSession().getNamedQuery( name );
+			org.hibernate.Query namedQuery = getSession().getNamedQuery( name );
+			try {
+				return new QueryImpl( namedQuery, this );
+			}
+			catch ( HibernateException he ) {
+				throw convert( he );
+			}
 		}
 		catch ( MappingException e ) {
 			throw new IllegalArgumentException( "Named query not found: " + name );
 		}
+	}
+
+	public <T> TypedQuery<T> createNamedQuery(String name, Class<T> resultClass) {
 		try {
-			return new QueryImpl( namedQuery, this );
+			org.hibernate.Query namedQuery = getSession().getNamedQuery( name );
+			try {
+				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 new IllegalArgumentException(
+							"Type specified for TypedQuery [" +
+									resultClass.getName() +
+									"] is incompatible with query return type [" +
+									namedQuery.getReturnTypes()[0].getReturnedClass() + "]"
+					);
+				}
+				return new QueryImpl<T>( namedQuery, this );
+			}
+			catch ( HibernateException he ) {
+				throw convert( he );
+			}
 		}
-		catch ( HibernateException he ) {
-			throwPersistenceException( he );
-			return null;
+		catch ( MappingException e ) {
+			throw new IllegalArgumentException( "Named query not found: " + name );
 		}
 	}
 
-	public <T> TypedQuery<T> createNamedQuery(String name, Class<T> resultClass) {
-		throw new UnsupportedOperationException( "Not yet implemented" );
-	}
 
-
 	public Query createNativeQuery(String sqlString) {
-		//adjustFlushMode();
 		try {
 			SQLQuery q = getSession().createSQLQuery( sqlString );
 			return new QueryImpl( q, this );
 		}
 		catch ( HibernateException he ) {
-			throwPersistenceException( he );
-			return null;
+			throw convert( he );
 		}
 	}
 
 	public Query createNativeQuery(String sqlString, Class resultClass) {
-		//adjustFlushMode();
 		try {
 			SQLQuery q = getSession().createSQLQuery( sqlString );
 			q.addEntity( "alias1", resultClass.getName(), LockMode.READ );
 			return new QueryImpl( q, this );
 		}
 		catch ( HibernateException he ) {
-			throwPersistenceException( he );
-			return null;
+			throw convert( he );
 		}
 	}
 
 	public Query createNativeQuery(String sqlString, String resultSetMapping) {
-		//adjustFlushMode();
 		try {
 			SQLQuery q = getSession().createSQLQuery( sqlString );
 			q.setResultSetMapping( resultSetMapping );
 			return new QueryImpl( q, this );
 		}
 		catch ( HibernateException he ) {
-			throwPersistenceException( he );
-			return null;
+			throw convert( he );
 		}
 	}
 
 	@SuppressWarnings("unchecked")
 	public <T> T getReference(Class<T> entityClass, Object primaryKey) {
-		//adjustFlushMode();
 		try {
 			return ( T ) getSession().load( entityClass, ( Serializable ) primaryKey );
 		}
@@ -241,14 +271,12 @@
 			throw new IllegalArgumentException( e.getMessage(), e );
 		}
 		catch ( HibernateException he ) {
-			throwPersistenceException( he );
-			return null;
+			throw convert( he );
 		}
 	}
 
 	@SuppressWarnings("unchecked")
 	public <A> A find(Class<A> entityClass, Object primaryKey) {
-		//adjustFlushMode();
 		try {
 			return ( A ) getSession().get( entityClass, ( Serializable ) primaryKey );
 		}
@@ -270,8 +298,7 @@
 			throw new IllegalArgumentException( e.getMessage(), e );
 		}
 		catch ( HibernateException he ) {
-			throwPersistenceException( he );
-			return null;
+			throw convert( he );
 		}
 	}
 
@@ -301,7 +328,6 @@
 
 	public void persist(Object entity) {
 		checkTransactionNeeded();
-		//adjustFlushMode();
 		try {
 			getSession().persist( entity );
 		}
@@ -309,14 +335,13 @@
 			throw new IllegalArgumentException( e.getMessage() );
 		}
 		catch ( HibernateException he ) {
-			throwPersistenceException( he );
+			throw convert( he );
 		}
 	}
 
 	@SuppressWarnings("unchecked")
 	public <A> A merge(A entity) {
 		checkTransactionNeeded();
-		//adjustFlushMode();
 		try {
 			return ( A ) getSession().merge( entity );
 		}
@@ -327,14 +352,12 @@
 			throw new IllegalArgumentException( e.getMessage(), e );
 		}
 		catch ( HibernateException he ) {
-			throwPersistenceException( he );
-			return null;
+			throw convert( he );
 		}
 	}
 
 	public void remove(Object entity) {
 		checkTransactionNeeded();
-		//adjustFlushMode();
 		try {
 			getSession().delete( entity );
 		}
@@ -342,13 +365,12 @@
 			throw new IllegalArgumentException( e.getMessage(), e );
 		}
 		catch ( HibernateException he ) {
-			throwPersistenceException( he );
+			throw convert( he );
 		}
 	}
 
 	public void refresh(Object entity) {
 		checkTransactionNeeded();
-		//adjustFlushMode();
 		try {
 			if ( !getSession().contains( entity ) ) {
 				throw new IllegalArgumentException( "Entity not managed" );
@@ -359,7 +381,7 @@
 			throw new IllegalArgumentException( e.getMessage(), e );
 		}
 		catch ( HibernateException he ) {
-			throwPersistenceException( he );
+			throw convert( he );
 		}
 	}
 
@@ -391,8 +413,7 @@
 			throw new IllegalArgumentException( e.getMessage(), e );
 		}
 		catch ( HibernateException he ) {
-			throwPersistenceException( he );
-			return false;
+			throw convert( he );
 		}
 	}
 
@@ -425,7 +446,7 @@
 			getSession().flush();
 		}
 		catch ( HibernateException he ) {
-			throwPersistenceException( he );
+			throw convert( he );
 		}
 	}
 
@@ -490,7 +511,7 @@
 			getSession().clear();
 		}
 		catch ( HibernateException he ) {
-			throwPersistenceException( he );
+			throw convert( he );
 		}
 	}
 
@@ -499,7 +520,7 @@
 			getSession().evict( entity );
 		}
 		catch ( HibernateException he ) {
-			throwPersistenceException( he );
+			throw convert( he );
 		}
 	}
 
@@ -672,14 +693,17 @@
 											log.trace( "skipping managed flushing" );
 										}
 									}
+									catch ( HibernateException he ) {
+										throw convert( he );
+									}
+									catch( PersistenceException pe ) {
+										handlePersistenceException( pe );
+										throw pe;
+									}
 									catch ( RuntimeException re ) {
-										//throwPersistenceException will mark the transaction as rollbacked
-										if ( re instanceof HibernateException ) {
-											throwPersistenceException( ( HibernateException ) re );
-										}
-										else {
-											throwPersistenceException( new PersistenceException( re ) );
-										}
+										PersistenceException wrapped = new PersistenceException( re );
+										handlePersistenceException( wrapped );
+										throw wrapped;
 									}
 								}
 
@@ -698,7 +722,7 @@
 										}
 									}
 									catch ( HibernateException e ) {
-										throwPersistenceException( e );
+										throw convert( e );
 									}
 								}
 							}
@@ -709,7 +733,7 @@
 				}
 			}
 			catch ( HibernateException he ) {
-				throwPersistenceException( he );
+				throw convert( he );
 			}
 		}
 		else {
@@ -735,35 +759,60 @@
 		tx = new TransactionImpl( this );
 	}
 
+	/**
+	 * {@inheritDoc}
+	 */
+	public void handlePersistenceException(PersistenceException e) {
+		if ( e instanceof NoResultException ) {
+			return;
+		}
+		if ( e instanceof NonUniqueResultException ) {
+			return;
+		}
+
+		try {
+			markAsRollback();
+		}
+		catch ( Exception ne ) {
+			//we do not want the subsequent exception to swallow the original one
+			log.error( "Unable to mark for rollback on PersistenceException: ", ne );
+		}
+	}
+
+	/**
+	 * {@inheritDoc}
+	 */
 	public void throwPersistenceException(PersistenceException e) {
-		if ( !( e instanceof NoResultException || e instanceof NonUniqueResultException ) ) {
-			try {
-				markAsRollback();
-			}
-			catch ( Exception ne ) {
-				//we do not want the subsequent exception to swallow the original one
-				log.error( "Unable to mark for rollback on PersistenceException: ", ne );
-			}
-		}
+		handlePersistenceException( e );
 		throw e;
 	}
 
-	public void throwPersistenceException(HibernateException e) {
+	/**
+	 * {@inheritDoc}
+	 */
+	public RuntimeException convert(HibernateException e) {
 		if ( e instanceof StaleStateException ) {
-			PersistenceException pe = wrapStaleStateException( ( StaleStateException ) e );
-			throwPersistenceException( pe );
+			PersistenceException converted = wrapStaleStateException( ( StaleStateException ) e );
+			handlePersistenceException( converted );
+			return converted;
 		}
 		else if ( e instanceof ObjectNotFoundException ) {
-			throwPersistenceException( new EntityNotFoundException( e.getMessage() ) );
+			EntityNotFoundException converted = new EntityNotFoundException( e.getMessage() );
+			handlePersistenceException( converted );
+			return converted;
 		}
 		else if ( e instanceof org.hibernate.NonUniqueResultException ) {
-			throwPersistenceException( new NonUniqueResultException( e.getMessage() ) );
+			NonUniqueResultException converted = new NonUniqueResultException( e.getMessage() );
+			handlePersistenceException( converted );
+			return converted;
 		}
 		else if ( e instanceof UnresolvableObjectException ) {
-			throwPersistenceException( new EntityNotFoundException( e.getMessage() ) );
+			EntityNotFoundException converted = new EntityNotFoundException( e.getMessage() );
+			handlePersistenceException( converted );
+			return converted;
 		}
 		else if ( e instanceof QueryException ) {
-			throw new IllegalArgumentException( e );
+			return new IllegalArgumentException( e );
 		}
 		else if ( e instanceof TransientObjectException ) {
 			try {
@@ -773,13 +822,25 @@
 				//we do not want the subsequent exception to swallow the original one
 				log.error( "Unable to mark for rollback on TransientObjectException: ", ne );
 			}
-			throw new IllegalStateException( e ); //Spec 3.2.3 Synchronization rules
+			return new IllegalStateException( e ); //Spec 3.2.3 Synchronization rules
 		}
 		else {
-			throwPersistenceException( new PersistenceException( e ) );
+			PersistenceException converted = new PersistenceException( e );
+			handlePersistenceException( converted );
+			return converted;
 		}
 	}
 
+	/**
+	 * {@inheritDoc}
+	 */
+	public void throwPersistenceException(HibernateException e) {
+		throw convert( e );
+	}
+
+	/**
+	 * {@inheritDoc}
+	 */
 	public PersistenceException wrapStaleStateException(StaleStateException e) {
 		PersistenceException pe;
 		if ( e instanceof StaleObjectStateException ) {

Added: core/trunk/entitymanager/src/main/java/org/hibernate/ejb/AbstractQueryImpl.java
===================================================================
--- core/trunk/entitymanager/src/main/java/org/hibernate/ejb/AbstractQueryImpl.java	                        (rev 0)
+++ core/trunk/entitymanager/src/main/java/org/hibernate/ejb/AbstractQueryImpl.java	2009-08-26 20:34:58 UTC (rev 17426)
@@ -0,0 +1,352 @@
+/*
+ * Hibernate, Relational Persistence for Idiomatic Java
+ *
+ * Copyright (c) 2009 by Red Hat Inc and/or its affiliates or by
+ * third-party contributors as indicated by either @author tags or express
+ * copyright attribution statements applied by the authors.  All
+ * third-party contributions are distributed under license by Red Hat Inc.
+ *
+ * This copyrighted material is made available to anyone wishing to use, modify,
+ * copy, or redistribute it subject to the terms and conditions of the GNU
+ * Lesser General Public License, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License
+ * for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this distribution; if not, write to:
+ * Free Software Foundation, Inc.
+ * 51 Franklin Street, Fifth Floor
+ * Boston, MA  02110-1301  USA
+ */
+package org.hibernate.ejb;
+
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Set;
+import javax.persistence.FlushModeType;
+import javax.persistence.Parameter;
+import javax.persistence.TransactionRequiredException;
+import javax.persistence.TypedQuery;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import org.hibernate.CacheMode;
+import org.hibernate.FlushMode;
+import org.hibernate.HibernateException;
+import org.hibernate.TypeMismatchException;
+import static org.hibernate.ejb.QueryHints.HINT_CACHEABLE;
+import static org.hibernate.ejb.QueryHints.HINT_CACHE_MODE;
+import static org.hibernate.ejb.QueryHints.HINT_CACHE_REGION;
+import static org.hibernate.ejb.QueryHints.HINT_COMMENT;
+import static org.hibernate.ejb.QueryHints.HINT_FETCH_SIZE;
+import static org.hibernate.ejb.QueryHints.HINT_FLUSH_MODE;
+import static org.hibernate.ejb.QueryHints.HINT_READONLY;
+import static org.hibernate.ejb.QueryHints.HINT_TIMEOUT;
+import org.hibernate.ejb.util.ConfigurationHelper;
+import org.hibernate.hql.QueryExecutionRequestException;
+
+/**
+ * Intended as a base class providing convenience in implementing both {@link javax.persistence.Query} and
+ * {@link javax.persistence.TypedQuery}.
+ * <p/>
+ * IMPL NOTE : This issue, and the reason for this distinction, is that criteria and hl.sql queries share no
+ * commonality currently in Hibernate internals.
+ *
+ * @author Steve Ebersole
+ */
+public abstract class AbstractQueryImpl<X> implements TypedQuery<X> {
+	private static final Logger log = LoggerFactory.getLogger( AbstractQueryImpl.class );
+
+	private final HibernateEntityManagerImplementor entityManager;
+
+	public AbstractQueryImpl(HibernateEntityManagerImplementor entityManager) {
+		this.entityManager = entityManager;
+	}
+
+	protected HibernateEntityManagerImplementor getEntityManager() {
+		return entityManager;
+	}
+
+	/**
+	 * Actually execute the update; all pre-requisites have been checked.
+	 *
+	 * @return The number of "affected rows".
+	 */
+	protected abstract int internalExecuteUpdate();
+
+	/**
+	 * {@inheritDoc}
+	 */
+	@SuppressWarnings({ "ThrowableInstanceNeverThrown" })
+	public int executeUpdate() {
+		try {
+			if ( ! entityManager.isTransactionInProgress() ) {
+				entityManager.throwPersistenceException( new TransactionRequiredException( "Executing an update/delete query" ) );
+				return 0;
+			}
+			return internalExecuteUpdate();
+		}
+		catch ( QueryExecutionRequestException he) {
+			throw new IllegalStateException(he);
+		}
+		catch( TypeMismatchException e ) {
+			throw new IllegalArgumentException(e);
+		}
+		catch ( HibernateException he) {
+			entityManager.throwPersistenceException( he );
+			return 0;
+		}
+	}
+
+	private int maxResults = -1;
+
+	/**
+	 * Apply the given max results value.
+	 *
+	 * @param maxResults The specified max results
+	 */
+	protected abstract void applyMaxResults(int maxResults);
+
+	/**
+	 * {@inheritDoc}
+	 */
+	public TypedQuery<X> setMaxResults(int maxResult) {
+		if ( maxResult < 0 ) {
+			throw new IllegalArgumentException(
+					"Negative value (" + maxResult + ") passed to setMaxResults"
+			);
+		}
+		this.maxResults = maxResult;
+		applyMaxResults( maxResult );
+		return this;
+	}
+
+	public int getSpecifiedMaxResults() {
+		return maxResults;
+	}
+
+	public int getMaxResults() {
+		return maxResults == -1
+				? Integer.MAX_VALUE // stupid spec... MAX_VALUE??
+				: maxResults;
+	}
+
+	private int firstResult;
+
+	/**
+	 * Apply the given first-result value.
+	 *
+	 * @param firstResult The specified first-result value.
+	 */
+	protected abstract void applyFirstResult(int firstResult);
+
+	public TypedQuery<X> setFirstResult(int firstResult) {
+		if ( firstResult < 0 ) {
+			throw new IllegalArgumentException(
+					"Negative value (" + firstResult + ") passed to setFirstResult"
+			);
+		}
+		this.firstResult = firstResult;
+		applyFirstResult( firstResult );
+		return this;
+	}
+
+	public int getFirstResult() {
+		return firstResult;
+	}
+
+	private Map<String, Object> hints;
+
+	/**
+	 * {@inheritDoc}
+	 */
+	public Map<String, Object> getHints() {
+		return hints;
+	}
+
+	protected abstract void applyTimeout(int timeout);
+
+	protected abstract void applyComment(String comment);
+
+	protected abstract void applyFetchSize(int fetchSize);
+
+	protected abstract void applyCacheable(boolean isCacheable);
+
+	protected abstract void applyCacheRegion(String regionName);
+
+	protected abstract void applyReadOnly(boolean isReadOnly);
+
+	protected abstract void applyCacheMode(CacheMode cacheMode);
+
+	protected abstract void applyFlushMode(FlushMode flushMode);
+
+	/**
+	 * {@inheritDoc}
+	 */
+	public TypedQuery<X> setHint(String hintName, Object value) {
+		boolean skipped = false;
+		try {
+			if ( HINT_TIMEOUT.equals( hintName ) ) {
+				applyTimeout( ConfigurationHelper.getInteger( value ) );
+			}
+			else if ( HINT_COMMENT.equals( hintName ) ) {
+				applyComment( (String) value );
+			}
+			else if ( HINT_FETCH_SIZE.equals( hintName ) ) {
+				applyFetchSize( ConfigurationHelper.getInteger( value ) );
+			}
+			else if ( HINT_CACHEABLE.equals( hintName ) ) {
+				applyCacheable( ConfigurationHelper.getBoolean( value ) );
+			}
+			else if ( HINT_CACHE_REGION.equals( hintName ) ) {
+				applyCacheRegion( (String) value );
+			}
+			else if ( HINT_READONLY.equals( hintName ) ) {
+				applyReadOnly( ConfigurationHelper.getBoolean( value ) );
+			}
+			else if ( HINT_CACHE_MODE.equals( hintName ) ) {
+				applyCacheMode( ConfigurationHelper.getCacheMode( value ) );
+			}
+			else if ( HINT_FLUSH_MODE.equals( hintName ) ) {
+				applyFlushMode( ConfigurationHelper.getFlushMode( value ) );
+			}
+			/* TODO:
+			else if ( "org.hibernate.lockMode".equals( hintName ) ) {
+				query.setLockMode( alias, lockMode );
+			}*/
+			else {
+				skipped = true;
+				log.info( "Ignoring unrecognized query hint [" + hintName + "]" );
+			}
+		}
+		catch ( ClassCastException e ) {
+			throw new IllegalArgumentException( "Value for hint" );
+		}
+
+		if ( !skipped ) {
+			if ( hints == null ) {
+				hints = new HashMap<String,Object>();
+			}
+			hints.put( hintName, value );
+		}
+
+		return this;
+	}
+
+	public Set<String> getSupportedHints() {
+		return QueryHints.getDefinedHints();
+	}
+
+	private FlushModeType jpaFlushMode;
+
+	public TypedQuery<X> setFlushMode(FlushModeType jpaFlushMode) {
+		this.jpaFlushMode = jpaFlushMode;
+		// TODO : treat as hint?
+		if ( jpaFlushMode == FlushModeType.AUTO ) {
+			applyFlushMode( FlushMode.AUTO );
+		}
+		else if ( jpaFlushMode == FlushModeType.COMMIT ) {
+			applyFlushMode( FlushMode.COMMIT );
+		}
+		return this;
+	}
+
+	protected FlushModeType getSpecifiedFlushMode() {
+		return jpaFlushMode;
+	}
+
+	public FlushModeType getFlushMode() {
+		return jpaFlushMode != null
+				? jpaFlushMode
+				: entityManager.getFlushMode();
+	}
+
+	private Map parameterBindings;
+
+	protected void registerParameterBinding(Parameter parameter, Object value) {
+		if ( value != null && parameter.getJavaType() != null ) {
+			if ( Collection.class.isInstance( value ) ) {
+				final Collection collection = (Collection) value;
+				// validate the elements...
+				for ( Object element : collection ) {
+					if ( ! parameter.getJavaType().isInstance( element ) ) {
+						throw new IllegalArgumentException(
+								"Parameter value [" + element + "] was not matching type [" +
+										parameter.getJavaType().getName() + "]"
+						);
+					}
+				}
+			}
+			else if ( value.getClass().isArray() ) {
+				final Object[] array = (Object[]) value;
+				for ( Object element : array ) {
+					if ( ! parameter.getJavaType().isInstance( element ) ) {
+						throw new IllegalArgumentException(
+								"Parameter value [" + element + "] was not matching type [" +
+										parameter.getJavaType().getName() + "]"
+						);
+					}
+				}
+			}
+			else {
+				if ( ! parameter.getJavaType().isInstance( value ) ) {
+					throw new IllegalArgumentException(
+							"Parameter value [" + value + "] was not matching type [" +
+									parameter.getJavaType().getName() + "]"
+					);
+				}
+			}
+		}
+
+		if ( parameterBindings == null ) {
+			parameterBindings = new HashMap();
+		}
+		parameterBindings.put( parameter, value );
+	}
+
+	/**
+	 * {@inheritDoc}
+	 */
+    public boolean isBound(Parameter<?> param) {
+		return parameterBindings != null && parameterBindings.containsKey( param );
+	}
+
+	/**
+	 * {@inheritDoc}
+	 */
+	@SuppressWarnings({ "unchecked" })
+	public <T> T getParameterValue(Parameter<T> param) {
+		if ( parameterBindings == null ) {
+			throw new IllegalStateException( "No parameters have been bound" );
+		}
+		try {
+			T value = (T) parameterBindings.get( param );
+			if ( value == null ) {
+				throw new IllegalStateException( "Parameter has not been bound" );
+			}
+			return value;
+		}
+		catch ( ClassCastException cce ) {
+			throw new IllegalStateException( "Encountered a parameter value type exception" );
+		}
+	}
+
+	/**
+	 * {@inheritDoc}
+	 */
+	public Object getParameterValue(String name) {
+		return getParameterValue( getParameter( name ) );
+	}
+
+	/**
+	 * {@inheritDoc}
+	 */
+	public Object getParameterValue(int position) {
+		return getParameterValue( getParameter( position ) );
+	}
+}

Modified: core/trunk/entitymanager/src/main/java/org/hibernate/ejb/HibernateEntityManagerImplementor.java
===================================================================
--- core/trunk/entitymanager/src/main/java/org/hibernate/ejb/HibernateEntityManagerImplementor.java	2009-08-26 14:40:41 UTC (rev 17425)
+++ core/trunk/entitymanager/src/main/java/org/hibernate/ejb/HibernateEntityManagerImplementor.java	2009-08-26 20:34:58 UTC (rev 17426)
@@ -1,9 +1,11 @@
 /*
- * Copyright (c) 2009, Red Hat Middleware LLC or third-party contributors as
- * indicated by the @author tags or express copyright attribution
- * statements applied by the authors.  All third-party contributions are
- * distributed under license by Red Hat Middleware LLC.
+ * Hibernate, Relational Persistence for Idiomatic Java
  *
+ * Copyright (c) 2009 by Red Hat Inc and/or its affiliates or by
+ * third-party contributors as indicated by either @author tags or express
+ * copyright attribution statements applied by the authors.  All
+ * third-party contributions are distributed under license by Red Hat Inc.
+ *
  * This copyrighted material is made available to anyone wishing to use, modify,
  * copy, or redistribute it subject to the terms and conditions of the GNU
  * Lesser General Public License, as published by the Free Software Foundation.
@@ -19,8 +21,6 @@
  * 51 Franklin Street, Fifth Floor
  * Boston, MA  02110-1301  USA
  */
-
-//$Id$
 package org.hibernate.ejb;
 
 import javax.persistence.PersistenceException;
@@ -29,13 +29,50 @@
 import org.hibernate.StaleStateException;
 
 /**
+ * Additional internal contracts for the Hibernate {@link javax.persistence.EntityManager} implementation.
+ *
  * @author Emmanuel Bernard
+ * @author Steve Ebersole
  */
 public interface HibernateEntityManagerImplementor extends HibernateEntityManager {
+	/**
+	 * Provides access to whether a transaction is currently in progress.
+	 *
+	 * @return True if a transaction is considered currently in progress; false otherwise.
+	 */
 	boolean isTransactionInProgress();
 
+	/**
+	 * Handles marking for rollback and other such operations that need to occur depending on the type of
+	 * exception being handled.
+	 *
+	 * @param e The exception being handled.
+	 */
+	public void handlePersistenceException(PersistenceException e);
+
+	/**
+	 * Delegates to {@link #handlePersistenceException} and then throws the given exception.
+	 *
+	 * @param e The exception being handled and finally thrown.
+	 */
 	public void throwPersistenceException(PersistenceException e);
 
+	/**
+	 * Converts a Hibernate-specific exception into a JPA-specified exception; note that the JPA sepcification makes use
+	 * of exceptions outside its exception hierarchy, though they are all runtime exceptions.
+	 * <p/>
+	 * Any appropriate/needed calls to {@link #handlePersistenceException} are also made.
+	 *
+	 * @param e The Hibernate excepton.
+	 * @return The JPA-specified exception
+	 */
+	public RuntimeException convert(HibernateException e);
+
+	/**
+	 * Delegates to {@link #convert} and then throws the given exception.
+	 *
+	 * @param e The exception being handled and finally thrown.
+	 */
 	public void throwPersistenceException(HibernateException e);
 
 	public PersistenceException wrapStaleStateException(StaleStateException e);

Modified: core/trunk/entitymanager/src/main/java/org/hibernate/ejb/HibernatePersistence.java
===================================================================
--- core/trunk/entitymanager/src/main/java/org/hibernate/ejb/HibernatePersistence.java	2009-08-26 14:40:41 UTC (rev 17425)
+++ core/trunk/entitymanager/src/main/java/org/hibernate/ejb/HibernatePersistence.java	2009-08-26 20:34:58 UTC (rev 17426)
@@ -1,9 +1,11 @@
 /*
- * Copyright (c) 2009, Red Hat Middleware LLC or third-party contributors as
- * indicated by the @author tags or express copyright attribution
- * statements applied by the authors.  All third-party contributions are
- * distributed under license by Red Hat Middleware LLC.
+ * Hibernate, Relational Persistence for Idiomatic Java
  *
+ * Copyright (c) 2009 by Red Hat Inc and/or its affiliates or by
+ * third-party contributors as indicated by either @author tags or express
+ * copyright attribution statements applied by the authors.  All
+ * third-party contributions are distributed under license by Red Hat Inc.
+ *
  * This copyrighted material is made available to anyone wishing to use, modify,
  * copy, or redistribute it subject to the terms and conditions of the GNU
  * Lesser General Public License, as published by the Free Software Foundation.
@@ -17,31 +19,16 @@
  * along with this distribution; if not, write to:
  * Free Software Foundation, Inc.
  * 51 Franklin Street, Fifth Floor
- * Boston, MA  02110-1301  USA
+ * Boston, MA  02110-1301  USA\
  */
-
-//$Id$
 package org.hibernate.ejb;
 
 import java.util.Map;
-import java.lang.reflect.Field;
-import java.lang.reflect.Member;
-import java.lang.reflect.Modifier;
-import java.lang.reflect.AccessibleObject;
-import java.lang.reflect.Method;
-import java.lang.reflect.InvocationTargetException;
 import javax.persistence.EntityManagerFactory;
-import javax.persistence.PersistenceException;
-import javax.persistence.spi.PersistenceUnitInfo;
 import javax.persistence.spi.LoadState;
+import javax.persistence.spi.PersistenceUnitInfo;
 
-import org.hibernate.Hibernate;
 import org.hibernate.ejb.util.PersistenceUtilHelper;
-import org.hibernate.intercept.FieldInterceptionHelper;
-import org.hibernate.intercept.FieldInterceptor;
-import org.hibernate.collection.PersistentCollection;
-import org.hibernate.proxy.HibernateProxy;
-import org.hibernate.proxy.LazyInitializer;
 
 /**
  * Hibernate EJB3 persistence provider implementation

Modified: core/trunk/entitymanager/src/main/java/org/hibernate/ejb/HibernateQuery.java
===================================================================
--- core/trunk/entitymanager/src/main/java/org/hibernate/ejb/HibernateQuery.java	2009-08-26 14:40:41 UTC (rev 17425)
+++ core/trunk/entitymanager/src/main/java/org/hibernate/ejb/HibernateQuery.java	2009-08-26 20:34:58 UTC (rev 17426)
@@ -1,9 +1,11 @@
 /*
- * Copyright (c) 2009, Red Hat Middleware LLC or third-party contributors as
- * indicated by the @author tags or express copyright attribution
- * statements applied by the authors.  All third-party contributions are
- * distributed under license by Red Hat Middleware LLC.
+ * Hibernate, Relational Persistence for Idiomatic Java
  *
+ * Copyright (c) 2009 by Red Hat Inc and/or its affiliates or by
+ * third-party contributors as indicated by either @author tags or express
+ * copyright attribution statements applied by the authors.  All
+ * third-party contributions are distributed under license by Red Hat Inc.
+ *
  * This copyrighted material is made available to anyone wishing to use, modify,
  * copy, or redistribute it subject to the terms and conditions of the GNU
  * Lesser General Public License, as published by the Free Software Foundation.
@@ -17,10 +19,8 @@
  * along with this distribution; if not, write to:
  * Free Software Foundation, Inc.
  * 51 Franklin Street, Fifth Floor
- * Boston, MA  02110-1301  USA
+ * Boston, MA  02110-1301  USA\
  */
-
-//$Id$
 package org.hibernate.ejb;
 
 import javax.persistence.Query;

Added: core/trunk/entitymanager/src/main/java/org/hibernate/ejb/QueryHints.java
===================================================================
--- core/trunk/entitymanager/src/main/java/org/hibernate/ejb/QueryHints.java	                        (rev 0)
+++ core/trunk/entitymanager/src/main/java/org/hibernate/ejb/QueryHints.java	2009-08-26 20:34:58 UTC (rev 17426)
@@ -0,0 +1,62 @@
+/*
+ * Hibernate, Relational Persistence for Idiomatic Java
+ *
+ * Copyright (c) 2009 by Red Hat Inc and/or its affiliates or by
+ * third-party contributors as indicated by either @author tags or express
+ * copyright attribution statements applied by the authors.  All
+ * third-party contributions are distributed under license by Red Hat Inc.
+ *
+ * This copyrighted material is made available to anyone wishing to use, modify,
+ * copy, or redistribute it subject to the terms and conditions of the GNU
+ * Lesser General Public License, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License
+ * for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this distribution; if not, write to:
+ * Free Software Foundation, Inc.
+ * 51 Franklin Street, Fifth Floor
+ * Boston, MA  02110-1301  USA\
+ */
+package org.hibernate.ejb;
+
+import java.util.Set;
+import java.util.HashSet;
+
+/**
+ * TODO : javadoc
+ *
+ * @author Steve Ebersole
+ */
+public class QueryHints {
+	public static final String HINT_TIMEOUT = "org.hibernate.timeout";
+	public static final String HINT_COMMENT = "org.hibernate.comment";
+	public static final String HINT_FETCH_SIZE = "org.hibernate.fetchSize";
+	public static final String HINT_CACHE_REGION = "org.hibernate.cacheRegion";
+	public static final String HINT_CACHEABLE = "org.hibernate.cacheable";
+	public static final String HINT_READONLY = "org.hibernate.readOnly";
+	public static final String HINT_CACHE_MODE = "org.hibernate.cacheMode";
+	public static final String HINT_FLUSH_MODE = "org.hibernate.flushMode";
+
+	private static final Set<String> HINTS = buildHintsSet();
+
+	private static Set<String> buildHintsSet() {
+		HashSet<String> hints = new HashSet<String>();
+		hints.add( HINT_TIMEOUT );
+		hints.add( HINT_COMMENT );
+		hints.add( HINT_FETCH_SIZE );
+		hints.add( HINT_CACHE_REGION );
+		hints.add( HINT_CACHEABLE );
+		hints.add( HINT_READONLY );
+		hints.add( HINT_CACHE_MODE );
+		hints.add( HINT_FLUSH_MODE );
+		return java.util.Collections.unmodifiableSet( hints );
+	}
+
+	public static Set<String> getDefinedHints() {
+		return HINTS;
+	}
+}

Modified: core/trunk/entitymanager/src/main/java/org/hibernate/ejb/QueryImpl.java
===================================================================
--- core/trunk/entitymanager/src/main/java/org/hibernate/ejb/QueryImpl.java	2009-08-26 14:40:41 UTC (rev 17425)
+++ core/trunk/entitymanager/src/main/java/org/hibernate/ejb/QueryImpl.java	2009-08-26 20:34:58 UTC (rev 17426)
@@ -1,9 +1,11 @@
 /*
- * Copyright (c) 2009, Red Hat Middleware LLC or third-party contributors as
- * indicated by the @author tags or express copyright attribution
- * statements applied by the authors.  All third-party contributions are
- * distributed under license by Red Hat Middleware LLC.
+ * Hibernate, Relational Persistence for Idiomatic Java
  *
+ * Copyright (c) 2009 by Red Hat Inc and/or its affiliates or by
+ * third-party contributors as indicated by either @author tags or express
+ * copyright attribution statements applied by the authors.  All
+ * third-party contributions are distributed under license by Red Hat Inc.
+ *
  * This copyrighted material is made available to anyone wishing to use, modify,
  * copy, or redistribute it subject to the terms and conditions of the GNU
  * Lesser General Public License, as published by the Free Software Foundation.
@@ -26,71 +28,187 @@
 import java.util.Calendar;
 import java.util.Collection;
 import java.util.Date;
+import java.util.HashSet;
 import java.util.List;
-import java.util.HashSet;
 import java.util.Set;
-import java.util.Map;
-import javax.persistence.FlushModeType;
+import javax.persistence.LockModeType;
 import javax.persistence.NoResultException;
 import javax.persistence.NonUniqueResultException;
+import javax.persistence.Parameter;
 import javax.persistence.Query;
 import javax.persistence.TemporalType;
-import static javax.persistence.TemporalType.*;
-import javax.persistence.TransactionRequiredException;
-import javax.persistence.LockModeType;
-import javax.persistence.Parameter;
+import static javax.persistence.TemporalType.DATE;
+import static javax.persistence.TemporalType.TIME;
+import static javax.persistence.TemporalType.TIMESTAMP;
+import javax.persistence.TypedQuery;
+import javax.persistence.PersistenceException;
 
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import org.hibernate.CacheMode;
 import org.hibernate.FlushMode;
 import org.hibernate.HibernateException;
 import org.hibernate.QueryParameterException;
 import org.hibernate.TypeMismatchException;
+import org.hibernate.engine.query.NamedParameterDescriptor;
+import org.hibernate.engine.query.OrdinalParameterDescriptor;
+import org.hibernate.hql.QueryExecutionRequestException;
 import org.hibernate.impl.AbstractQueryImpl;
-import org.hibernate.ejb.util.ConfigurationHelper;
-import org.hibernate.hql.QueryExecutionRequestException;
 
 /**
+ * Hibernate implementation of both the {@link Query} and {@link TypedQuery} contracts.
+ *
  * @author <a href="mailto:gavin at hibernate.org">Gavin King</a>
  * @author Emmanuel Bernard
+ * @author Steve Ebersole
  */
-public class QueryImpl implements Query, HibernateQuery {
+public class QueryImpl<X> extends org.hibernate.ejb.AbstractQueryImpl<X> implements TypedQuery<X>, HibernateQuery {
+	private static final Logger log = LoggerFactory.getLogger( QueryImpl.class );
+
 	private org.hibernate.Query query;
-	private HibernateEntityManagerImplementor em;
-	private Boolean isPositional = null;
-	private int maxResults = -1;
-	private int firstResult;
+	private Set<Integer> jpaPositionalIndices;
+	private Set<Parameter<?>> parameters;
 
 	public QueryImpl(org.hibernate.Query query, AbstractEntityManagerImpl em) {
+		super( em );
 		this.query = query;
-		this.em = em;
+		extractParameterInfo();
 	}
 
-	public org.hibernate.Query getHibernateQuery() {
-		return query;
-	}
+	@SuppressWarnings({ "unchecked" })
+	private void extractParameterInfo() {
+		if ( ! AbstractQueryImpl.class.isInstance( query ) ) {
+			throw new IllegalStateException( "Unknown query type for parameter extraction" );
+		}
 
-	public int executeUpdate() {
-		try {
-			if ( ! em.isTransactionInProgress() ) {
-				em.throwPersistenceException( new TransactionRequiredException( "Executing an update/delete query" ) );
-				return 0;
+		HashSet<Parameter<?>> parameters = new HashSet<Parameter<?>>();
+		AbstractQueryImpl queryImpl = AbstractQueryImpl.class.cast( query );
+
+		// extract named params
+		for ( String name : (Set<String>) queryImpl.getParameterMetadata().getNamedParameterNames() ) {
+			final NamedParameterDescriptor descriptor =
+					queryImpl.getParameterMetadata().getNamedParameterDescriptor( name );
+			final ParameterImpl parameter = new ParameterImpl(
+					name,
+					descriptor.getExpectedType() == null
+							? null
+							: descriptor.getExpectedType().getReturnedClass()
+			);
+			parameters.add( parameter );
+			if ( descriptor.isJpaStyle() ) {
+				if ( jpaPositionalIndices == null ) {
+					jpaPositionalIndices = new HashSet<Integer>();
+				}
+				jpaPositionalIndices.add( Integer.valueOf( name ) );
 			}
-			return query.executeUpdate();
 		}
-		catch (QueryExecutionRequestException he) {
-			throw new IllegalStateException(he);
+
+		// extract positional parameters
+		for ( int i = 0, max = queryImpl.getParameterMetadata().getOrdinalParameterCount(); i < max; i++ ) {
+			final OrdinalParameterDescriptor descriptor =
+					queryImpl.getParameterMetadata().getOrdinalParameterDescriptor( i+1 );
+			ParameterImpl parameter = new ParameterImpl(
+					descriptor.getOrdinalPosition() + 1,
+					descriptor.getExpectedType() == null
+							? null
+							: descriptor.getExpectedType().getReturnedClass()
+			);
+			parameters.add( parameter );
+			Integer position = descriptor.getOrdinalPosition();
+			if ( jpaPositionalIndices != null && jpaPositionalIndices.contains( position ) ) {
+				log.warn( "Parameter position [" + position + "] occurred as both JPA and Hibernate positional parameter" );
+			}
 		}
-		catch( TypeMismatchException e ) {
-			throw new IllegalArgumentException(e);
+
+		this.parameters = java.util.Collections.unmodifiableSet( parameters );
+	}
+
+	private static class ParameterImpl implements Parameter {
+		private final String name;
+		private final Integer position;
+		private final Class javaType;
+
+		private ParameterImpl(String name, Class javaType) {
+			this.name = name;
+			this.javaType = javaType;
+			this.position = null;
 		}
-		catch (HibernateException he) {
-			em.throwPersistenceException( he );
-			return 0;
+
+		private ParameterImpl(Integer position, Class javaType) {
+			this.position = position;
+			this.javaType = javaType;
+			this.name = null;
 		}
+
+		public String getName() {
+			return name;
+		}
+
+		public Integer getPosition() {
+			return position;
+		}
+
+		public Class getJavaType() {
+			return javaType;
+		}
 	}
 
-	public List getResultList() {
+	public org.hibernate.Query getHibernateQuery() {
+		return query;
+	}
+
+	protected int internalExecuteUpdate() {
+		return query.executeUpdate();
+	}
+
+	protected void applyMaxResults(int maxResults) {
+		query.setMaxResults( maxResults );
+	}
+
+	protected void applyFirstResult(int firstResult) {
+		query.setFirstResult( firstResult );
+	}
+
+	protected void applyTimeout(int timeout) {
+		query.setTimeout( timeout );
+	}
+
+	protected void applyComment(String comment) {
+		query.setComment( comment );
+	}
+
+	protected void applyFetchSize(int fetchSize) {
+		query.setFetchSize( fetchSize );
+	}
+
+	protected void applyCacheable(boolean isCacheable) {
+		query.setCacheable( isCacheable );
+	}
+
+	protected void applyCacheRegion(String regionName) {
+		query.setCacheRegion( regionName );
+	}
+
+	protected void applyReadOnly(boolean isReadOnly) {
+		query.setReadOnly( isReadOnly );
+	}
+
+	protected void applyCacheMode(CacheMode cacheMode) {
+		query.setCacheMode( cacheMode );
+	}
+
+	protected void applyFlushMode(FlushMode flushMode) {
+		query.setFlushMode( flushMode );
+	}
+
+	/**
+	 * {@inheritDoc}
+	 */
+	@SuppressWarnings({ "unchecked" })
+	public List<X> getResultList() {
 		try {
-			return query.list();
+			return (List<X>) query.list();
 		}
 		catch (QueryExecutionRequestException he) {
 			throw new IllegalStateException(he);
@@ -99,40 +217,39 @@
 			throw new IllegalArgumentException(e);
 		}
 		catch (HibernateException he) {
-			em.throwPersistenceException( he );
-			return null;
+			throw getEntityManager().convert( he );
 		}
 	}
 
-	public Object getSingleResult() {
+	/**
+	 * {@inheritDoc}
+	 */
+	@SuppressWarnings({ "unchecked" })
+	public X getSingleResult() {
 		try {
-			List result;
-			/* Avoid OOME if the list() is huge (user faulty query) by limiting the query to 2 elements max */
-			//FIXME: get rid of this impl binding (HHH-3432)
-			if ( query instanceof AbstractQueryImpl ) {
-				if (maxResults != 1) query.setMaxResults( 2 ); //avoid OOME if the list is huge
-				result = query.list();
-				if ( maxResults != -1 ) {
-					query.setMaxResults( maxResults ); //put back the original value
-				}
-				else {
-					AbstractQueryImpl queryImpl = AbstractQueryImpl.class.cast( query );
-					queryImpl.getSelection().setMaxRows( null );
-				}
+			boolean mucked = false;
+			// IMPL NOTE : the mucking with max results here is attempting to help the user from shooting themselves
+			//		in the foot in the case where they have a large query by limiting the query results to 2 max
+			if ( getSpecifiedMaxResults() != 1 ) {
+				mucked = true;
+				query.setMaxResults( 2 ); //avoid OOME if the list is huge
 			}
-			else {
-				//we can't do much because we cannot reset the maxResults => do the full list call
-				//Not tremendously bad as the user is doing a fault here anyway by calling getSingleREsults on a big list
-				result = query.list();
+			List<X> result = (List<X>) query.list();
+			if ( mucked ) {
+				query.setMaxResults( getSpecifiedMaxResults() );
 			}
 
 			if ( result.size() == 0 ) {
-				em.throwPersistenceException( new NoResultException( "No entity found for query" ) );
+				NoResultException nre = new NoResultException( "No entity found for query" );
+				getEntityManager().handlePersistenceException( nre );
+				throw nre;
 			}
 			else if ( result.size() > 1 ) {
-				Set uniqueResult = new HashSet(result);
+				Set<X> uniqueResult = new HashSet<X>(result);
 				if ( uniqueResult.size() > 1 ) {
-					em.throwPersistenceException( new NonUniqueResultException( "result returns more than one elements") );
+					NonUniqueResultException nure = new NonUniqueResultException( "result returns more than one elements" );
+					getEntityManager().handlePersistenceException( nure );
+					throw nure;
 				}
 				else {
 					return uniqueResult.iterator().next();
@@ -140,9 +257,8 @@
 
 			}
 			else {
-				return result.get(0);
+				return result.get( 0 );
 			}
-			return null; //should never happen
 		}
 		catch (QueryExecutionRequestException he) {
 			throw new IllegalStateException(he);
@@ -151,93 +267,56 @@
 			throw new IllegalArgumentException(e);
 		}
 		catch (HibernateException he) {
-			em.throwPersistenceException( he );
-			return null;
+			throw getEntityManager().convert( he );
 		}
 	}
 
-	public Query setMaxResults(int maxResult) {
-		if ( maxResult < 0 ) {
-			throw new IllegalArgumentException(
-					"Negative ("
-							+ maxResult
-							+ ") parameter passed in to setMaxResults"
-			);
+	public <T> TypedQuery<X> setParameter(Parameter<T> param, T value) {
+		if ( ! parameters.contains( param ) ) {
+			throw new IllegalArgumentException( "Specified parameter was not found in query" );
 		}
-		this.maxResults = maxResult;
-		query.setMaxResults( maxResult );
+		if ( param.getName() != null ) {
+			// a named param, for not delegate out.  Eventually delegate *into* this method...
+			setParameter( param.getName(), value );
+		}
+		else {
+			setParameter( param.getPosition(), value );
+		}
 		return this;
 	}
 
-	public int getMaxResults() {
-		return maxResults == -1 ? Integer.MAX_VALUE : maxResults; //stupid spec MAX_VALUE??
-	}
-
-	public Query setFirstResult(int firstResult) {
-		if ( firstResult < 0 ) {
-			throw new IllegalArgumentException(
-					"Negative ("
-							+ firstResult
-							+ ") parameter passed in to setFirstResult"
-			);
+	public TypedQuery<X> setParameter(Parameter<Date> param, Date value, TemporalType temporalType) {
+		if ( ! parameters.contains( param ) ) {
+			throw new IllegalArgumentException( "Specified parameter was not found in query" );
 		}
-		query.setFirstResult( firstResult );
-		this.firstResult = firstResult;
+		if ( param.getName() != null ) {
+			// a named param, for not delegate out.  Eventually delegate *into* this method...
+			setParameter( param.getName(), value, temporalType );
+		}
+		else {
+			setParameter( param.getPosition(), value, temporalType );
+		}
 		return this;
 	}
 
-	public int getFirstResult() {
-		return firstResult;
-	}
-
-	public Query setHint(String hintName, Object value) {
-		try {
-			if ( "org.hibernate.timeout".equals( hintName ) ) {
-				query.setTimeout( ConfigurationHelper.getInteger( value ) );
-			}
-			else if ( "org.hibernate.comment".equals( hintName ) ) {
-				query.setComment( (String) value );
-			}
-			else if ( "org.hibernate.fetchSize".equals( hintName ) ) {
-				query.setFetchSize( ConfigurationHelper.getInteger( value ) );
-			}
-			else if ( "org.hibernate.cacheRegion".equals( hintName ) ) {
-				query.setCacheRegion( (String) value );
-			}
-			else if ( "org.hibernate.cacheable".equals( hintName ) ) {
-				query.setCacheable( ConfigurationHelper.getBoolean( value ) );
-			}
-			else if ( "org.hibernate.readOnly".equals( hintName ) ) {
-				query.setReadOnly( ConfigurationHelper.getBoolean( value ) );
-			}
-			else if ( "org.hibernate.cacheMode".equals( hintName ) ) {
-				query.setCacheMode( ConfigurationHelper.getCacheMode( value ) );
-			}
-			else if ( "org.hibernate.flushMode".equals( hintName ) ) {
-				query.setFlushMode( ConfigurationHelper.getFlushMode( value ) );
-			}
-			//TODO:
-			/*else if ( "org.hibernate.lockMode".equals( hintName ) ) {
-				query.setLockMode( alias, lockMode );
-			}*/
+	public TypedQuery<X> setParameter(Parameter<Calendar> param, Calendar value, TemporalType temporalType) {
+		if ( ! parameters.contains( param ) ) {
+			throw new IllegalArgumentException( "Specified parameter was not found in query" );
 		}
-		catch (ClassCastException e) {
-			throw new IllegalArgumentException( "Value for hint" );
+		if ( param.getName() != null ) {
+			// a named param, for not delegate out.  Eventually delegate *into* this method...
+			setParameter( param.getName(), value, temporalType );
 		}
+		else {
+			setParameter( param.getPosition(), value, temporalType );
+		}
 		return this;
 	}
 
-	public Map<String, Object> getHints() {
-		//FIXME
-		return null;  //To change body of implemented methods use File | Settings | File Templates.
-	}
-
-	public Set<String> getSupportedHints() {
-		//FIXME
-		return null;  //To change body of implemented methods use File | Settings | File Templates.
-	}
-
-	public Query setParameter(String name, Object value) {
+	/**
+	 * {@inheritDoc}
+	 */
+	public TypedQuery<X> setParameter(String name, Object value) {
 		try {
 			if ( value instanceof Collection ) {
 				query.setParameterList( name, (Collection) value );
@@ -245,18 +324,21 @@
 			else {
 				query.setParameter( name, value );
 			}
+			registerParameterBinding( getParameter( name ), value );
 			return this;
 		}
 		catch (QueryParameterException e) {
 			throw new IllegalArgumentException( e );
 		}
 		catch (HibernateException he) {
-			em.throwPersistenceException( he );
-			return null;
+			throw getEntityManager().convert( he );
 		}
 	}
 
-	public Query setParameter(String name, Date value, TemporalType temporalType) {
+	/**
+	 * {@inheritDoc}
+	 */
+	public TypedQuery<X> setParameter(String name, Date value, TemporalType temporalType) {
 		try {
 			if ( temporalType == DATE ) {
 				query.setDate( name, value );
@@ -267,18 +349,21 @@
 			else if ( temporalType == TIMESTAMP ) {
 				query.setTimestamp( name, value );
 			}
+			registerParameterBinding( getParameter( name ), value );
 			return this;
 		}
 		catch (QueryParameterException e) {
 			throw new IllegalArgumentException( e );
 		}
 		catch (HibernateException he) {
-			em.throwPersistenceException( he );
-			return null;
+			throw getEntityManager().convert( he );
 		}
 	}
 
-	public Query setParameter(String name, Calendar value, TemporalType temporalType) {
+	/**
+	 * {@inheritDoc}
+	 */
+	public TypedQuery<X> setParameter(String name, Calendar value, TemporalType temporalType) {
 		try {
 			if ( temporalType == DATE ) {
 				query.setCalendarDate( name, value );
@@ -289,24 +374,28 @@
 			else if ( temporalType == TIMESTAMP ) {
 				query.setCalendar( name, value );
 			}
+			registerParameterBinding( getParameter(name), value );
 			return this;
 		}
 		catch (QueryParameterException e) {
 			throw new IllegalArgumentException( e );
 		}
 		catch (HibernateException he) {
-			em.throwPersistenceException( he );
-			return null;
+			throw getEntityManager().convert( he );
 		}
 	}
 
-	public Query setParameter(int position, Object value) {
+	/**
+	 * {@inheritDoc}
+	 */
+	public TypedQuery<X> setParameter(int position, Object value) {
 		try {
-			if ( isPositionalParameter() ) {
+			if ( isJpaPositionalParameter( position ) ) {
 				this.setParameter( Integer.toString( position ), value );
 			}
 			else {
 				query.setParameter( position - 1, value );
+				registerParameterBinding( getParameter( position ), value );
 			}
 			return this;
 		}
@@ -314,35 +403,20 @@
 			throw new IllegalArgumentException( e );
 		}
 		catch (HibernateException he) {
-			em.throwPersistenceException( he );
-			return null;
+			throw getEntityManager().convert( he );
 		}
 	}
 
-	private boolean isPositionalParameter() {
-		if (isPositional == null) {
-			//compute it
-			String queryString = query.getQueryString();
-			int index = queryString.indexOf( '?' );
-			//there is a ? and the following char is a digit
-			if (index == -1) {
-				//no ?
-				isPositional = true;
-			}
-			else if ( index == queryString.length() - 1 ) {
-				// "... ?"
-				isPositional = false;
-			}
-			else {
-				isPositional = Character.isDigit( queryString.charAt( index + 1 ) );
-			}
-		}
-		return isPositional;
+	private boolean isJpaPositionalParameter(int position) {
+		return jpaPositionalIndices != null && jpaPositionalIndices.contains( position );
 	}
 
-	public Query setParameter(int position, Date value, TemporalType temporalType) {
+	/**
+	 * {@inheritDoc}
+	 */
+	public TypedQuery<X> setParameter(int position, Date value, TemporalType temporalType) {
 		try {
-			if ( isPositionalParameter() ) {
+			if ( isJpaPositionalParameter( position ) ) {
 				String name = Integer.toString( position );
 				this.setParameter( name, value, temporalType );
 			}
@@ -356,6 +430,7 @@
 				else if ( temporalType == TIMESTAMP ) {
 					query.setTimestamp( position - 1, value );
 				}
+				registerParameterBinding( getParameter( position ), value );
 			}
 			return this;
 		}
@@ -363,14 +438,16 @@
 			throw new IllegalArgumentException( e );
 		}
 		catch (HibernateException he) {
-			em.throwPersistenceException( he );
-			return null;
+			throw getEntityManager().convert( he );
 		}
 	}
 
-	public Query setParameter(int position, Calendar value, TemporalType temporalType) {
+	/**
+	 * {@inheritDoc}
+	 */
+	public TypedQuery<X> setParameter(int position, Calendar value, TemporalType temporalType) {
 		try {
-			if ( isPositionalParameter() ) {
+			if ( isJpaPositionalParameter( position ) ) {
 				String name = Integer.toString( position );
 				this.setParameter( name, value, temporalType );
 			}
@@ -384,6 +461,7 @@
 				else if ( temporalType == TIMESTAMP ) {
 					query.setCalendar( position - 1, value );
 				}
+				registerParameterBinding( getParameter( position ), value );
 			}
 			return this;
 		}
@@ -391,83 +469,117 @@
 			throw new IllegalArgumentException( e );
 		}
 		catch (HibernateException he) {
-			em.throwPersistenceException( he );
-			return null;
+			throw getEntityManager().convert( he );
 		}
 	}
 
-	//FIXME
+	/**
+	 * {@inheritDoc}
+	 */
 	public Set<Parameter<?>> getParameters() {
-		return null;  //To change body of implemented methods use File | Settings | File Templates.
+		return parameters;
 	}
 
-	//FIXME
+	/**
+	 * {@inheritDoc}
+	 */
 	public Parameter<?> getParameter(String name) {
-		return null;  //To change body of implemented methods use File | Settings | File Templates.
+		if ( name == null ) {
+			throw new IllegalArgumentException( "Name of parameter to locate cannot be null" );
+		}
+		for ( Parameter parameter : parameters ) {
+			if ( name.equals( parameter.getName() ) ) {
+				return parameter;
+			}
+		}
+		throw new IllegalArgumentException( "Unable to locate parameter named [" + name + "]" );
 	}
 
-	//FIXME
+	/**
+	 * {@inheritDoc}
+	 */
 	public Parameter<?> getParameter(int position) {
-		return null;  //To change body of implemented methods use File | Settings | File Templates.
+		if ( isJpaPositionalParameter( position ) ) {
+			return getParameter( Integer.toString( position ) );
+		}
+		else {
+			for ( Parameter parameter : parameters ) {
+				if ( parameter.getPosition() != null && position == parameter.getPosition() ) {
+					return parameter;
+				}
+			}
+			throw new IllegalArgumentException( "Unable to locate parameter with position [" + position + "]" );
+		}
 	}
 
-	//FIXME
+	/**
+	 * {@inheritDoc}
+	 */
+	@SuppressWarnings({ "unchecked" })
 	public <T> Parameter<T> getParameter(String name, Class<T> type) {
-		return null;  //To change body of implemented methods use File | Settings | File Templates.
+		Parameter param = getParameter( name );
+		if ( param.getJavaType() != null ) {
+			// we were able to determine the expected type during analysis, so validate it here
+			throw new IllegalArgumentException(
+					"Parameter type [" + param.getJavaType().getName() +
+							"] is not assignment compatible with requested type [" +
+							type.getName() + "]"
+			);
+		}
+		return param;
 	}
 
-	//FIXME
+	/**
+	 * {@inheritDoc}
+	 */
+	@SuppressWarnings({ "unchecked" })
 	public <T> Parameter<T> getParameter(int position, Class<T> type) {
-		return null;  //To change body of implemented methods use File | Settings | File Templates.
-	}
-
-	//FIXME
-	public boolean isBound(Parameter<?> param) {
-		return false;  //To change body of implemented methods use File | Settings | File Templates.
-	}
-
-	//FIXME
-	public <T> T getParameterValue(Parameter<T> param) {
-		return null;  //To change body of implemented methods use File | Settings | File Templates.
-	}
-
-	//FIXME
-	public Object getParameterValue(String name) {
-		return null;  //To change body of implemented methods use File | Settings | File Templates.
-	}
-
-	//FIXME
-	public Object getParameterValue(int position) {
-		return null;  //To change body of implemented methods use File | Settings | File Templates.
-	}
-
-	public Query setFlushMode(FlushModeType flushMode) {
-		if ( flushMode == FlushModeType.AUTO ) {
-			query.setFlushMode( FlushMode.AUTO );
+		Parameter param = getParameter( position );
+		if ( param.getJavaType() != null ) {
+			// we were able to determine the expected type during analysis, so validate it here
+			throw new IllegalArgumentException(
+					"Parameter type [" + param.getJavaType().getName() +
+							"] is not assignment compatible with requested type [" +
+							type.getName() + "]"
+			);
 		}
-		else if ( flushMode == FlushModeType.COMMIT ) {
-			query.setFlushMode( FlushMode.COMMIT );
-		}
-		return this;
+		return param;
 	}
 
-	public FlushModeType getFlushMode() {
-		//FIXME
-		return null;  //To change body of implemented methods use File | Settings | File Templates.
+	/**
+	 * {@inheritDoc}
+	 */
+	public TypedQuery<X> setLockMode(LockModeType lockModeType) {
+		// TODO : aye aye aye
+		throw new UnsupportedOperationException( "Not yet implemented" );
 	}
 
-	public Query setLockMode(LockModeType lockModeType) {
-		//FIXME
-		return null;  //To change body of implemented methods use File | Settings | File Templates.
-	}
-
+	/**
+	 * {@inheritDoc}
+	 */
 	public LockModeType getLockMode() {
-		//FIXME
-		return null;  //To change body of implemented methods use File | Settings | File Templates.
+		return LockModeType.NONE;
 	}
 
+	/**
+	 * {@inheritDoc}
+	 */
+	@SuppressWarnings({ "unchecked" })
 	public <T> T unwrap(Class<T> tClass) {
-		//FIXME
-		return null;  //To change body of implemented methods use File | Settings | File Templates.
+		if ( org.hibernate.Query.class.isAssignableFrom( tClass ) ) {
+			return (T) query;
+		}
+		else {
+			try {
+				return (T) this;
+			}
+			catch ( ClassCastException cce ) {
+				PersistenceException pe = new PersistenceException(
+						"Unsupported unwrap target type [" + tClass.getName() + "]"
+				);
+				getEntityManager().handlePersistenceException( pe );
+				throw pe;
+			}
+		}
 	}
 }



More information about the hibernate-commits mailing list