diff --git a/core/src/main/java/org/hibernate/impl/AbstractQueryImpl.java b/core/src/main/java/org/hibernate/impl/AbstractQueryImpl.java
index f2ea5e2ab6..f395af810a 100644
--- a/core/src/main/java/org/hibernate/impl/AbstractQueryImpl.java
+++ b/core/src/main/java/org/hibernate/impl/AbstractQueryImpl.java
@@ -116,6 +116,10 @@ public abstract class AbstractQueryImpl implements Query {
this.parameterMetadata = parameterMetadata;
}
+ public ParameterMetadata getParameterMetadata() {
+ return parameterMetadata;
+ }
+
public String toString() {
return StringHelper.unqualify( getClass().getName() ) + '(' + queryString + ')';
}
@@ -161,7 +165,13 @@ public abstract class AbstractQueryImpl implements Query {
}
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;
}
diff --git a/entitymanager/src/main/java/org/hibernate/ejb/AbstractEntityManagerImpl.java b/entitymanager/src/main/java/org/hibernate/ejb/AbstractEntityManagerImpl.java
index 2a44ab3d6e..d04e898234 100755
--- a/entitymanager/src/main/java/org/hibernate/ejb/AbstractEntityManagerImpl.java
+++ b/entitymanager/src/main/java/org/hibernate/ejb/AbstractEntityManagerImpl.java
@@ -1,8 +1,10 @@
/*
- * 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
@@ -80,6 +82,7 @@ import org.hibernate.util.JTAHelper;
/**
* @author Gavin King
* @author Emmanuel Bernard
+ * @author Steve Ebersole
*/
@SuppressWarnings("unchecked")
public abstract class AbstractEntityManagerImpl implements HibernateEntityManagerImplementor, Serializable {
@@ -115,19 +118,34 @@ public abstract class AbstractEntityManagerImpl implements HibernateEntityManage
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( getSession().createQuery( jpaqlString ), this );
}
catch ( HibernateException he ) {
- throwPersistenceException( he );
- return null;
+ throw convert( he );
}
}
- public TypedQuery createQuery(String qlString, Class resultClass) {
- throw new UnsupportedOperationException( "Not yet implemented" );
+ public TypedQuery createQuery(String jpaqlString, Class 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( hqlQuery, this );
+ }
+ catch ( HibernateException he ) {
+ throw convert( he );
+ }
}
public TypedQuery createQuery(CriteriaQuery criteriaQuery) {
@@ -165,69 +183,81 @@ public abstract class AbstractEntityManagerImpl implements HibernateEntityManage
}
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 );
}
- try {
- return new QueryImpl( namedQuery, this );
- }
- catch ( HibernateException he ) {
- throwPersistenceException( he );
- return null;
- }
}
public TypedQuery createNamedQuery(String name, Class resultClass) {
- throw new UnsupportedOperationException( "Not yet implemented" );
+ try {
+ 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( namedQuery, this );
+ }
+ catch ( HibernateException he ) {
+ throw convert( he );
+ }
+ }
+ catch ( MappingException e ) {
+ throw new IllegalArgumentException( "Named query not found: " + name );
+ }
}
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 getReference(Class entityClass, Object primaryKey) {
- //adjustFlushMode();
try {
return ( T ) getSession().load( entityClass, ( Serializable ) primaryKey );
}
@@ -241,14 +271,12 @@ public abstract class AbstractEntityManagerImpl implements HibernateEntityManage
throw new IllegalArgumentException( e.getMessage(), e );
}
catch ( HibernateException he ) {
- throwPersistenceException( he );
- return null;
+ throw convert( he );
}
}
@SuppressWarnings("unchecked")
public A find(Class entityClass, Object primaryKey) {
- //adjustFlushMode();
try {
return ( A ) getSession().get( entityClass, ( Serializable ) primaryKey );
}
@@ -270,8 +298,7 @@ public abstract class AbstractEntityManagerImpl implements HibernateEntityManage
throw new IllegalArgumentException( e.getMessage(), e );
}
catch ( HibernateException he ) {
- throwPersistenceException( he );
- return null;
+ throw convert( he );
}
}
@@ -301,7 +328,6 @@ public abstract class AbstractEntityManagerImpl implements HibernateEntityManage
public void persist(Object entity) {
checkTransactionNeeded();
- //adjustFlushMode();
try {
getSession().persist( entity );
}
@@ -309,14 +335,13 @@ public abstract class AbstractEntityManagerImpl implements HibernateEntityManage
throw new IllegalArgumentException( e.getMessage() );
}
catch ( HibernateException he ) {
- throwPersistenceException( he );
+ throw convert( he );
}
}
@SuppressWarnings("unchecked")
public A merge(A entity) {
checkTransactionNeeded();
- //adjustFlushMode();
try {
return ( A ) getSession().merge( entity );
}
@@ -327,14 +352,12 @@ public abstract class AbstractEntityManagerImpl implements HibernateEntityManage
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 @@ public abstract class AbstractEntityManagerImpl implements HibernateEntityManage
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 @@ public abstract class AbstractEntityManagerImpl implements HibernateEntityManage
throw new IllegalArgumentException( e.getMessage(), e );
}
catch ( HibernateException he ) {
- throwPersistenceException( he );
+ throw convert( he );
}
}
@@ -391,8 +413,7 @@ public abstract class AbstractEntityManagerImpl implements HibernateEntityManage
throw new IllegalArgumentException( e.getMessage(), e );
}
catch ( HibernateException he ) {
- throwPersistenceException( he );
- return false;
+ throw convert( he );
}
}
@@ -425,7 +446,7 @@ public abstract class AbstractEntityManagerImpl implements HibernateEntityManage
getSession().flush();
}
catch ( HibernateException he ) {
- throwPersistenceException( he );
+ throw convert( he );
}
}
@@ -490,7 +511,7 @@ public abstract class AbstractEntityManagerImpl implements HibernateEntityManage
getSession().clear();
}
catch ( HibernateException he ) {
- throwPersistenceException( he );
+ throw convert( he );
}
}
@@ -499,7 +520,7 @@ public abstract class AbstractEntityManagerImpl implements HibernateEntityManage
getSession().evict( entity );
}
catch ( HibernateException he ) {
- throwPersistenceException( he );
+ throw convert( he );
}
}
@@ -672,14 +693,17 @@ public abstract class AbstractEntityManagerImpl implements HibernateEntityManage
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 @@ public abstract class AbstractEntityManagerImpl implements HibernateEntityManage
}
}
catch ( HibernateException e ) {
- throwPersistenceException( e );
+ throw convert( e );
}
}
}
@@ -709,7 +733,7 @@ public abstract class AbstractEntityManagerImpl implements HibernateEntityManage
}
}
catch ( HibernateException he ) {
- throwPersistenceException( he );
+ throw convert( he );
}
}
else {
@@ -735,35 +759,60 @@ public abstract class AbstractEntityManagerImpl implements HibernateEntityManage
tx = new TransactionImpl( this );
}
- 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 );
- }
+ /**
+ * {@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) {
+ 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 @@ public abstract class AbstractEntityManagerImpl implements HibernateEntityManage
//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 ) {
diff --git a/entitymanager/src/main/java/org/hibernate/ejb/AbstractQueryImpl.java b/entitymanager/src/main/java/org/hibernate/ejb/AbstractQueryImpl.java
new file mode 100644
index 0000000000..27d1a28805
--- /dev/null
+++ b/entitymanager/src/main/java/org/hibernate/ejb/AbstractQueryImpl.java
@@ -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}.
+ *
+ * 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 implements TypedQuery {
+ 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 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 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 hints;
+
+ /**
+ * {@inheritDoc}
+ */
+ public Map 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 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();
+ }
+ hints.put( hintName, value );
+ }
+
+ return this;
+ }
+
+ public Set getSupportedHints() {
+ return QueryHints.getDefinedHints();
+ }
+
+ private FlushModeType jpaFlushMode;
+
+ public TypedQuery 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 getParameterValue(Parameter 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 ) );
+ }
+}
diff --git a/entitymanager/src/main/java/org/hibernate/ejb/HibernateEntityManagerImplementor.java b/entitymanager/src/main/java/org/hibernate/ejb/HibernateEntityManagerImplementor.java
index 6e0d56b618..850e7d48e7 100644
--- a/entitymanager/src/main/java/org/hibernate/ejb/HibernateEntityManagerImplementor.java
+++ b/entitymanager/src/main/java/org/hibernate/ejb/HibernateEntityManagerImplementor.java
@@ -1,8 +1,10 @@
/*
- * 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
@@ -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.HibernateException;
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.
+ *
+ * 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);
diff --git a/entitymanager/src/main/java/org/hibernate/ejb/HibernatePersistence.java b/entitymanager/src/main/java/org/hibernate/ejb/HibernatePersistence.java
index 36fdd45983..e2b7dd4680 100755
--- a/entitymanager/src/main/java/org/hibernate/ejb/HibernatePersistence.java
+++ b/entitymanager/src/main/java/org/hibernate/ejb/HibernatePersistence.java
@@ -1,8 +1,10 @@
/*
- * 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
@@ -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
diff --git a/entitymanager/src/main/java/org/hibernate/ejb/HibernateQuery.java b/entitymanager/src/main/java/org/hibernate/ejb/HibernateQuery.java
index cd7a40584f..499c4b3983 100755
--- a/entitymanager/src/main/java/org/hibernate/ejb/HibernateQuery.java
+++ b/entitymanager/src/main/java/org/hibernate/ejb/HibernateQuery.java
@@ -1,8 +1,10 @@
/*
- * 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
@@ -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;
diff --git a/entitymanager/src/main/java/org/hibernate/ejb/QueryHints.java b/entitymanager/src/main/java/org/hibernate/ejb/QueryHints.java
new file mode 100644
index 0000000000..2ef5e8c562
--- /dev/null
+++ b/entitymanager/src/main/java/org/hibernate/ejb/QueryHints.java
@@ -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 HINTS = buildHintsSet();
+
+ private static Set buildHintsSet() {
+ HashSet hints = new HashSet();
+ 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 getDefinedHints() {
+ return HINTS;
+ }
+}
diff --git a/entitymanager/src/main/java/org/hibernate/ejb/QueryImpl.java b/entitymanager/src/main/java/org/hibernate/ejb/QueryImpl.java
index d09fdaa317..c09552bb07 100755
--- a/entitymanager/src/main/java/org/hibernate/ejb/QueryImpl.java
+++ b/entitymanager/src/main/java/org/hibernate/ejb/QueryImpl.java
@@ -1,8 +1,10 @@
/*
- * 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
@@ -26,55 +28,187 @@ package org.hibernate.ejb;
import java.util.Calendar;
import java.util.Collection;
import java.util.Date;
-import java.util.List;
import java.util.HashSet;
+import java.util.List;
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.impl.AbstractQueryImpl;
-import org.hibernate.ejb.util.ConfigurationHelper;
+import org.hibernate.engine.query.NamedParameterDescriptor;
+import org.hibernate.engine.query.OrdinalParameterDescriptor;
import org.hibernate.hql.QueryExecutionRequestException;
+import org.hibernate.impl.AbstractQueryImpl;
/**
+ * Hibernate implementation of both the {@link Query} and {@link TypedQuery} contracts.
+ *
* @author Gavin King
* @author Emmanuel Bernard
+ * @author Steve Ebersole
*/
-public class QueryImpl implements Query, HibernateQuery {
+public class QueryImpl extends org.hibernate.ejb.AbstractQueryImpl implements TypedQuery, 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 jpaPositionalIndices;
+ private Set> parameters;
public QueryImpl(org.hibernate.Query query, AbstractEntityManagerImpl em) {
+ super( em );
this.query = query;
- this.em = em;
+ extractParameterInfo();
+ }
+
+ @SuppressWarnings({ "unchecked" })
+ private void extractParameterInfo() {
+ if ( ! AbstractQueryImpl.class.isInstance( query ) ) {
+ throw new IllegalStateException( "Unknown query type for parameter extraction" );
+ }
+
+ HashSet> parameters = new HashSet>();
+ AbstractQueryImpl queryImpl = AbstractQueryImpl.class.cast( query );
+
+ // extract named params
+ for ( String name : (Set) 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();
+ }
+ jpaPositionalIndices.add( Integer.valueOf( name ) );
+ }
+ }
+
+ // 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" );
+ }
+ }
+
+ 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;
+ }
+
+ 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 org.hibernate.Query getHibernateQuery() {
return query;
}
- public int executeUpdate() {
+ 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 getResultList() {
try {
- if ( ! em.isTransactionInProgress() ) {
- em.throwPersistenceException( new TransactionRequiredException( "Executing an update/delete query" ) );
- return 0;
- }
- return query.executeUpdate();
+ return (List) query.list();
}
catch (QueryExecutionRequestException he) {
throw new IllegalStateException(he);
@@ -83,56 +217,39 @@ public class QueryImpl implements Query, HibernateQuery {
throw new IllegalArgumentException(e);
}
catch (HibernateException he) {
- em.throwPersistenceException( he );
- return 0;
+ throw getEntityManager().convert( he );
}
}
- public List getResultList() {
+ /**
+ * {@inheritDoc}
+ */
+ @SuppressWarnings({ "unchecked" })
+ public X getSingleResult() {
try {
- return query.list();
- }
- catch (QueryExecutionRequestException he) {
- throw new IllegalStateException(he);
- }
- catch( TypeMismatchException e ) {
- throw new IllegalArgumentException(e);
- }
- catch (HibernateException he) {
- em.throwPersistenceException( he );
- return null;
- }
- }
-
- public Object 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 result = (List) 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 uniqueResult = new HashSet(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 @@ public class QueryImpl implements Query, HibernateQuery {
}
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 @@ public class QueryImpl implements Query, HibernateQuery {
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 TypedQuery setParameter(Parameter param, T value) {
+ if ( ! parameters.contains( param ) ) {
+ throw new IllegalArgumentException( "Specified parameter was not found in query" );
}
- this.maxResults = maxResult;
- query.setMaxResults( maxResult );
- 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"
- );
+ if ( param.getName() != null ) {
+ // a named param, for not delegate out. Eventually delegate *into* this method...
+ setParameter( param.getName(), value );
}
- query.setFirstResult( firstResult );
- this.firstResult = firstResult;
- 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 );
- }*/
- }
- catch (ClassCastException e) {
- throw new IllegalArgumentException( "Value for hint" );
+ else {
+ setParameter( param.getPosition(), value );
}
return this;
}
- public Map getHints() {
- //FIXME
- return null; //To change body of implemented methods use File | Settings | File Templates.
+ public TypedQuery setParameter(Parameter param, Date value, TemporalType temporalType) {
+ if ( ! parameters.contains( param ) ) {
+ throw new IllegalArgumentException( "Specified parameter was not found in query" );
+ }
+ 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 Set getSupportedHints() {
- //FIXME
- return null; //To change body of implemented methods use File | Settings | File Templates.
+ public TypedQuery setParameter(Parameter param, Calendar value, TemporalType temporalType) {
+ if ( ! parameters.contains( param ) ) {
+ throw new IllegalArgumentException( "Specified parameter was not found in query" );
+ }
+ 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 Query setParameter(String name, Object value) {
+ /**
+ * {@inheritDoc}
+ */
+ public TypedQuery setParameter(String name, Object value) {
try {
if ( value instanceof Collection ) {
query.setParameterList( name, (Collection) value );
@@ -245,18 +324,21 @@ public class QueryImpl implements Query, HibernateQuery {
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 setParameter(String name, Date value, TemporalType temporalType) {
try {
if ( temporalType == DATE ) {
query.setDate( name, value );
@@ -267,18 +349,21 @@ public class QueryImpl implements Query, HibernateQuery {
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 setParameter(String name, Calendar value, TemporalType temporalType) {
try {
if ( temporalType == DATE ) {
query.setCalendarDate( name, value );
@@ -289,24 +374,28 @@ public class QueryImpl implements Query, HibernateQuery {
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 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 @@ public class QueryImpl implements Query, HibernateQuery {
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 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 @@ public class QueryImpl implements Query, HibernateQuery {
else if ( temporalType == TIMESTAMP ) {
query.setTimestamp( position - 1, value );
}
+ registerParameterBinding( getParameter( position ), value );
}
return this;
}
@@ -363,14 +438,16 @@ public class QueryImpl implements Query, HibernateQuery {
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 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 @@ public class QueryImpl implements Query, HibernateQuery {
else if ( temporalType == TIMESTAMP ) {
query.setCalendar( position - 1, value );
}
+ registerParameterBinding( getParameter( position ), value );
}
return this;
}
@@ -391,83 +469,117 @@ public class QueryImpl implements Query, HibernateQuery {
throw new IllegalArgumentException( e );
}
catch (HibernateException he) {
- em.throwPersistenceException( he );
- return null;
+ throw getEntityManager().convert( he );
}
}
- //FIXME
+ /**
+ * {@inheritDoc}
+ */
public Set> 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 Parameter getParameter(String name, Class 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 Parameter getParameter(int position, Class 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 getParameterValue(Parameter 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.
- }
-
- public Query setLockMode(LockModeType lockModeType) {
- //FIXME
- return null; //To change body of implemented methods use File | Settings | File Templates.
+ /**
+ * {@inheritDoc}
+ */
+ public TypedQuery setLockMode(LockModeType lockModeType) {
+ // TODO : aye aye aye
+ throw new UnsupportedOperationException( "Not yet implemented" );
}
+ /**
+ * {@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 unwrap(Class 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;
+ }
+ }
}
}