diff --git a/hibernate-entitymanager/src/main/java/org/hibernate/jpa/internal/QueryImpl.java b/hibernate-entitymanager/src/main/java/org/hibernate/jpa/internal/QueryImpl.java index 8dc78500a4..6a69cd5f5d 100755 --- a/hibernate-entitymanager/src/main/java/org/hibernate/jpa/internal/QueryImpl.java +++ b/hibernate-entitymanager/src/main/java/org/hibernate/jpa/internal/QueryImpl.java @@ -61,6 +61,8 @@ import org.hibernate.jpa.internal.util.ConfigurationHelper; import org.hibernate.jpa.internal.util.LockModeTypeHelper; import org.hibernate.jpa.spi.AbstractEntityManagerImpl; import org.hibernate.jpa.spi.AbstractQueryImpl; +import org.hibernate.jpa.spi.ParameterBind; +import org.hibernate.jpa.spi.ParameterRegistration; import org.hibernate.type.CompositeCustomType; import org.hibernate.type.Type; import org.jboss.logging.Logger; @@ -112,7 +114,7 @@ public class QueryImpl extends AbstractQueryImpl implements TypedQuery, else if ( descriptor.getExpectedType() != null ) { javaType = descriptor.getExpectedType().getReturnedClass(); } - registerParameter( new ParameterRegistrationImpl( query, name, javaType ) ); + registerParameter( new ParameterRegistrationImpl( this, query, name, javaType ) ); if ( descriptor.isJpaStyle() ) { if ( jpaPositionalIndices == null ) { jpaPositionalIndices = new HashSet(); @@ -125,7 +127,7 @@ public class QueryImpl extends AbstractQueryImpl implements TypedQuery, for ( int i = 0, max = parameterMetadata.getOrdinalParameterCount(); i < max; i++ ) { final OrdinalParameterDescriptor descriptor = parameterMetadata.getOrdinalParameterDescriptor( i + 1 ); Class javaType = descriptor.getExpectedType() == null ? null : descriptor.getExpectedType().getReturnedClass(); - registerParameter( new ParameterRegistrationImpl( query, i+1, javaType ) ); + registerParameter( new ParameterRegistrationImpl( this, query, i+1, javaType ) ); Integer position = descriptor.getOrdinalPosition(); if ( jpaPositionalIndices != null && jpaPositionalIndices.contains(position) ) { LOG.parameterPositionOccurredAsBothJpaAndHibernatePositionalParameter(position); @@ -147,7 +149,8 @@ public class QueryImpl extends AbstractQueryImpl implements TypedQuery, } private static class ParameterRegistrationImpl implements ParameterRegistration { - private final org.hibernate.Query query; + private final Query jpaQuery; + private final org.hibernate.Query nativeQuery; private final String name; private final Integer position; @@ -155,20 +158,35 @@ public class QueryImpl extends AbstractQueryImpl implements TypedQuery, private ParameterBind bind; - private ParameterRegistrationImpl(org.hibernate.Query query, String name, Class javaType) { - this.query = query; + private ParameterRegistrationImpl( + Query jpaQuery, + org.hibernate.Query nativeQuery, + String name, + Class javaType) { + this.jpaQuery = jpaQuery; + this.nativeQuery = nativeQuery; this.name = name; this.javaType = javaType; this.position = null; } - private ParameterRegistrationImpl(org.hibernate.Query query, Integer position, Class javaType) { - this.query = query; + private ParameterRegistrationImpl( + Query jpaQuery, + org.hibernate.Query nativeQuery, + Integer position, + Class javaType) { + this.jpaQuery = jpaQuery; + this.nativeQuery = nativeQuery; this.position = position; this.javaType = javaType; this.name = null; } + @Override + public Query getQuery() { + return jpaQuery; + } + @Override public String getName() { return name; @@ -202,14 +220,14 @@ public class QueryImpl extends AbstractQueryImpl implements TypedQuery, if ( name != null ) { if ( value instanceof Collection ) { - query.setParameterList( name, (Collection) value ); + nativeQuery.setParameterList( name, (Collection) value ); } else { - query.setParameter( name, value ); + nativeQuery.setParameter( name, value ); } } else { - query.setParameter( position-1, value ); + nativeQuery.setParameter( position - 1, value ); } bind = new ParameterBindImpl( value, null ); @@ -222,48 +240,48 @@ public class QueryImpl extends AbstractQueryImpl implements TypedQuery, if ( Date.class.isInstance( value ) ) { if ( name != null ) { if ( specifiedTemporalType == DATE ) { - query.setDate( name, (Date) value ); + nativeQuery.setDate( name, (Date) value ); } else if ( specifiedTemporalType == TIME ) { - query.setTime( name, (Date) value ); + nativeQuery.setTime( name, (Date) value ); } else if ( specifiedTemporalType == TIMESTAMP ) { - query.setTimestamp( name, (Date) value ); + nativeQuery.setTimestamp( name, (Date) value ); } } else { if ( specifiedTemporalType == DATE ) { - query.setDate( position-1, (Date) value ); + nativeQuery.setDate( position - 1, (Date) value ); } else if ( specifiedTemporalType == TIME ) { - query.setTime( position-1, (Date) value ); + nativeQuery.setTime( position - 1, (Date) value ); } else if ( specifiedTemporalType == TIMESTAMP ) { - query.setTimestamp( position-1, (Date) value ); + nativeQuery.setTimestamp( position - 1, (Date) value ); } } } else if ( Calendar.class.isInstance( value ) ) { if ( name != null ) { if ( specifiedTemporalType == DATE ) { - query.setCalendarDate( name, (Calendar) value ); + nativeQuery.setCalendarDate( name, (Calendar) value ); } else if ( specifiedTemporalType == TIME ) { throw new IllegalArgumentException( "not yet implemented" ); } else if ( specifiedTemporalType == TIMESTAMP ) { - query.setCalendar( name, (Calendar) value ); + nativeQuery.setCalendar( name, (Calendar) value ); } } else { if ( specifiedTemporalType == DATE ) { - query.setCalendarDate( position-1, (Calendar) value ); + nativeQuery.setCalendarDate( position - 1, (Calendar) value ); } else if ( specifiedTemporalType == TIME ) { throw new IllegalArgumentException( "not yet implemented" ); } else if ( specifiedTemporalType == TIMESTAMP ) { - query.setCalendar( position-1, (Calendar) value ); + nativeQuery.setCalendar( position - 1, (Calendar) value ); } } } diff --git a/hibernate-entitymanager/src/main/java/org/hibernate/jpa/internal/StoredProcedureQueryImpl.java b/hibernate-entitymanager/src/main/java/org/hibernate/jpa/internal/StoredProcedureQueryImpl.java index 6ddb0bdf4b..e0c629572c 100644 --- a/hibernate-entitymanager/src/main/java/org/hibernate/jpa/internal/StoredProcedureQueryImpl.java +++ b/hibernate-entitymanager/src/main/java/org/hibernate/jpa/internal/StoredProcedureQueryImpl.java @@ -41,6 +41,8 @@ import java.util.List; import org.hibernate.CacheMode; import org.hibernate.FlushMode; import org.hibernate.LockMode; +import org.hibernate.jpa.spi.ParameterBind; +import org.hibernate.jpa.spi.ParameterRegistration; import org.hibernate.procedure.NoSuchParameterException; import org.hibernate.procedure.ParameterStrategyException; import org.hibernate.procedure.ProcedureCall; @@ -76,7 +78,7 @@ public class StoredProcedureQueryImpl extends BaseQueryImpl implements StoredPro super( entityManager ); this.procedureCall = memento.makeProcedureCall( entityManager.getSession() ); for ( org.hibernate.procedure.ParameterRegistration nativeParamReg : procedureCall.getRegisteredParameters() ) { - registerParameter( new ParameterRegistrationImpl( nativeParamReg ) ); + registerParameter( new ParameterRegistrationImpl( this, nativeParamReg ) ); } } @@ -122,6 +124,7 @@ public class StoredProcedureQueryImpl extends BaseQueryImpl implements StoredPro entityManager().checkOpen( true ); registerParameter( new ParameterRegistrationImpl( + this, procedureCall.registerParameter( position, type, mode ) ) ); @@ -134,6 +137,7 @@ public class StoredProcedureQueryImpl extends BaseQueryImpl implements StoredPro entityManager().checkOpen( true ); registerParameter( new ParameterRegistrationImpl( + this, procedureCall.registerParameter( parameterName, type, mode ) ) ); @@ -407,11 +411,15 @@ public class StoredProcedureQueryImpl extends BaseQueryImpl implements StoredPro } private static class ParameterRegistrationImpl implements ParameterRegistration { + private final StoredProcedureQueryImpl query; private final org.hibernate.procedure.ParameterRegistration nativeParamRegistration; private ParameterBind bind; - private ParameterRegistrationImpl(org.hibernate.procedure.ParameterRegistration nativeParamRegistration) { + public ParameterRegistrationImpl( + StoredProcedureQueryImpl query, + org.hibernate.procedure.ParameterRegistration nativeParamRegistration) { + this.query = query; this.nativeParamRegistration = nativeParamRegistration; } @@ -430,6 +438,11 @@ public class StoredProcedureQueryImpl extends BaseQueryImpl implements StoredPro return nativeParamRegistration.getType(); } + @Override + public Query getQuery() { + return query; + } + @Override public ParameterMode getMode() { return nativeParamRegistration.getMode(); diff --git a/hibernate-entitymanager/src/main/java/org/hibernate/jpa/spi/BaseQueryImpl.java b/hibernate-entitymanager/src/main/java/org/hibernate/jpa/spi/BaseQueryImpl.java index 9424aa265f..aa3c625b56 100644 --- a/hibernate-entitymanager/src/main/java/org/hibernate/jpa/spi/BaseQueryImpl.java +++ b/hibernate-entitymanager/src/main/java/org/hibernate/jpa/spi/BaseQueryImpl.java @@ -27,7 +27,6 @@ import javax.persistence.CacheRetrieveMode; import javax.persistence.CacheStoreMode; import javax.persistence.FlushModeType; import javax.persistence.Parameter; -import javax.persistence.ParameterMode; import javax.persistence.Query; import javax.persistence.TemporalType; import java.util.Calendar; @@ -409,7 +408,12 @@ public abstract class BaseQueryImpl implements Query { protected ParameterRegistration findParameterRegistration(Parameter parameter) { if ( ParameterRegistration.class.isInstance( parameter ) ) { - return (ParameterRegistration) parameter; + final ParameterRegistration reg = (ParameterRegistration) parameter; + // validate the parameter source + if ( reg.getQuery() != this ) { + throw new IllegalArgumentException( "Passed Parameter was from different Query" ); + } + return reg; } else { if ( parameter.getName() != null ) { @@ -440,45 +444,6 @@ public abstract class BaseQueryImpl implements Query { protected abstract boolean isJpaPositionalParameter(int position); - /** - * Hibernate specific extension to the JPA {@link javax.persistence.Parameter} contract. Used here to track - * information known about the parameter. - */ - protected static interface ParameterRegistration extends Parameter { - /** - * Retrieves the parameter "mode" which describes how the parameter is defined in the actual database procedure - * definition (is it an INPUT parameter? An OUTPUT parameter? etc). - * - * @return The parameter mode. - */ - public ParameterMode getMode(); - - /** - * Can we bind (set) values on this parameter? Generally this is {@code true}, but would not be in the case - * of parameters with OUT or REF_CURSOR mode. - * - * @return Whether the parameter is bindable (can set be called). - */ - public boolean isBindable(); - - public void bindValue(T value); - - public void bindValue(T value, TemporalType specifiedTemporalType); - - public ParameterBind getBind(); - } - - /** - * Represents the value currently bound to a particular parameter. - * - * @param - */ - protected static interface ParameterBind { - public T getValue(); - - public TemporalType getSpecifiedTemporalType(); - } - protected static class ParameterBindImpl implements ParameterBind { private final T value; private final TemporalType specifiedTemporalType; diff --git a/hibernate-entitymanager/src/main/java/org/hibernate/jpa/spi/ParameterBind.java b/hibernate-entitymanager/src/main/java/org/hibernate/jpa/spi/ParameterBind.java new file mode 100644 index 0000000000..31f7b900f6 --- /dev/null +++ b/hibernate-entitymanager/src/main/java/org/hibernate/jpa/spi/ParameterBind.java @@ -0,0 +1,49 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2013, Red Hat Inc. 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 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.jpa.spi; + +import javax.persistence.TemporalType; + +/** + * Represents the value currently bound to a particular (bindable) parameter. + * + * @param + * + * @author Steve Ebersole + */ +public interface ParameterBind { + /** + * Access the bound value + * + * @return The bound value + */ + public T getValue(); + + /** + * The temporal type that will be used to "interpret" Date-like values (if applicable). + * + * @return The temporal type, or {@code null} + */ + public TemporalType getSpecifiedTemporalType(); +} diff --git a/hibernate-entitymanager/src/main/java/org/hibernate/jpa/spi/ParameterRegistration.java b/hibernate-entitymanager/src/main/java/org/hibernate/jpa/spi/ParameterRegistration.java new file mode 100644 index 0000000000..d1df5bdd80 --- /dev/null +++ b/hibernate-entitymanager/src/main/java/org/hibernate/jpa/spi/ParameterRegistration.java @@ -0,0 +1,86 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2013, Red Hat Inc. 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 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.jpa.spi; + +import javax.persistence.Parameter; +import javax.persistence.ParameterMode; +import javax.persistence.Query; +import javax.persistence.TemporalType; + +/** + * Hibernate specific extension to the JPA {@link javax.persistence.Parameter} contract as known to the + * {@link javax.persistence.Query} and {@link javax.persistence.StoredProcedureQuery} implementations. Used to track + * information known about the parameter. + *

+ * For parameter information as known to JPA criteria queries, see {@link org.hibernate.jpa.criteria.expression.ParameterExpressionImpl} + * instead. + * + * @author Steve Ebersole + */ +public interface ParameterRegistration extends Parameter { + /** + * Access to the query that this parameter belongs to. + * + * @return The defining query + */ + public Query getQuery(); + + /** + * Retrieves the parameter "mode" which describes how the parameter is defined in the actual database procedure + * definition (is it an INPUT parameter? An OUTPUT parameter? etc). + * + * @return The parameter mode. + */ + public ParameterMode getMode(); + + /** + * Can we bind (set) values on this parameter? Generally this is {@code true}, but would not be in the case + * of parameters with OUT or REF_CURSOR mode. + * + * @return Whether the parameter is bindable (can set be called). + */ + public boolean isBindable(); + + /** + * If bindable, bind the value. + * + * @param value The value to bind. + */ + public void bindValue(T value); + + /** + * If bindable, bind the value using the specific temporal type. + * + * @param value The value to bind + * @param specifiedTemporalType The temporal type to use in binding + */ + public void bindValue(T value, TemporalType specifiedTemporalType); + + /** + * If bindable, get the current binding. + * + * @return The current binding + */ + public ParameterBind getBind(); +}