Skip to content

Commit 3d595fe

Browse files
committed
HHH-8419 - Tie javax.persistence.Parameter instance to javax.persistence.Query instance
1 parent 742b1b4 commit 3d595fe

5 files changed

Lines changed: 194 additions & 63 deletions

File tree

hibernate-entitymanager/src/main/java/org/hibernate/jpa/internal/QueryImpl.java

Lines changed: 38 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,8 @@
6161
import org.hibernate.jpa.internal.util.LockModeTypeHelper;
6262
import org.hibernate.jpa.spi.AbstractEntityManagerImpl;
6363
import org.hibernate.jpa.spi.AbstractQueryImpl;
64+
import org.hibernate.jpa.spi.ParameterBind;
65+
import org.hibernate.jpa.spi.ParameterRegistration;
6466
import org.hibernate.type.CompositeCustomType;
6567
import org.hibernate.type.Type;
6668
import org.jboss.logging.Logger;
@@ -112,7 +114,7 @@ private void extractParameterInfo(Map<String,Class> namedParameterTypeRedefiniti
112114
else if ( descriptor.getExpectedType() != null ) {
113115
javaType = descriptor.getExpectedType().getReturnedClass();
114116
}
115-
registerParameter( new ParameterRegistrationImpl( query, name, javaType ) );
117+
registerParameter( new ParameterRegistrationImpl( this, query, name, javaType ) );
116118
if ( descriptor.isJpaStyle() ) {
117119
if ( jpaPositionalIndices == null ) {
118120
jpaPositionalIndices = new HashSet<Integer>();
@@ -125,7 +127,7 @@ else if ( descriptor.getExpectedType() != null ) {
125127
for ( int i = 0, max = parameterMetadata.getOrdinalParameterCount(); i < max; i++ ) {
126128
final OrdinalParameterDescriptor descriptor = parameterMetadata.getOrdinalParameterDescriptor( i + 1 );
127129
Class javaType = descriptor.getExpectedType() == null ? null : descriptor.getExpectedType().getReturnedClass();
128-
registerParameter( new ParameterRegistrationImpl( query, i+1, javaType ) );
130+
registerParameter( new ParameterRegistrationImpl( this, query, i+1, javaType ) );
129131
Integer position = descriptor.getOrdinalPosition();
130132
if ( jpaPositionalIndices != null && jpaPositionalIndices.contains(position) ) {
131133
LOG.parameterPositionOccurredAsBothJpaAndHibernatePositionalParameter(position);
@@ -147,28 +149,44 @@ private boolean mightNeedRedefinition(Class javaType, Type expectedType) {
147149
}
148150

149151
private static class ParameterRegistrationImpl<T> implements ParameterRegistration<T> {
150-
private final org.hibernate.Query query;
152+
private final Query jpaQuery;
153+
private final org.hibernate.Query nativeQuery;
151154

152155
private final String name;
153156
private final Integer position;
154157
private final Class<T> javaType;
155158

156159
private ParameterBind<T> bind;
157160

158-
private ParameterRegistrationImpl(org.hibernate.Query query, String name, Class<T> javaType) {
159-
this.query = query;
161+
private ParameterRegistrationImpl(
162+
Query jpaQuery,
163+
org.hibernate.Query nativeQuery,
164+
String name,
165+
Class<T> javaType) {
166+
this.jpaQuery = jpaQuery;
167+
this.nativeQuery = nativeQuery;
160168
this.name = name;
161169
this.javaType = javaType;
162170
this.position = null;
163171
}
164172

165-
private ParameterRegistrationImpl(org.hibernate.Query query, Integer position, Class<T> javaType) {
166-
this.query = query;
173+
private ParameterRegistrationImpl(
174+
Query jpaQuery,
175+
org.hibernate.Query nativeQuery,
176+
Integer position,
177+
Class<T> javaType) {
178+
this.jpaQuery = jpaQuery;
179+
this.nativeQuery = nativeQuery;
167180
this.position = position;
168181
this.javaType = javaType;
169182
this.name = null;
170183
}
171184

185+
@Override
186+
public Query getQuery() {
187+
return jpaQuery;
188+
}
189+
172190
@Override
173191
public String getName() {
174192
return name;
@@ -202,14 +220,14 @@ public void bindValue(T value) {
202220

203221
if ( name != null ) {
204222
if ( value instanceof Collection ) {
205-
query.setParameterList( name, (Collection) value );
223+
nativeQuery.setParameterList( name, (Collection) value );
206224
}
207225
else {
208-
query.setParameter( name, value );
226+
nativeQuery.setParameter( name, value );
209227
}
210228
}
211229
else {
212-
query.setParameter( position-1, value );
230+
nativeQuery.setParameter( position - 1, value );
213231
}
214232

215233
bind = new ParameterBindImpl<T>( value, null );
@@ -222,48 +240,48 @@ public void bindValue(T value, TemporalType specifiedTemporalType) {
222240
if ( Date.class.isInstance( value ) ) {
223241
if ( name != null ) {
224242
if ( specifiedTemporalType == DATE ) {
225-
query.setDate( name, (Date) value );
243+
nativeQuery.setDate( name, (Date) value );
226244
}
227245
else if ( specifiedTemporalType == TIME ) {
228-
query.setTime( name, (Date) value );
246+
nativeQuery.setTime( name, (Date) value );
229247
}
230248
else if ( specifiedTemporalType == TIMESTAMP ) {
231-
query.setTimestamp( name, (Date) value );
249+
nativeQuery.setTimestamp( name, (Date) value );
232250
}
233251
}
234252
else {
235253
if ( specifiedTemporalType == DATE ) {
236-
query.setDate( position-1, (Date) value );
254+
nativeQuery.setDate( position - 1, (Date) value );
237255
}
238256
else if ( specifiedTemporalType == TIME ) {
239-
query.setTime( position-1, (Date) value );
257+
nativeQuery.setTime( position - 1, (Date) value );
240258
}
241259
else if ( specifiedTemporalType == TIMESTAMP ) {
242-
query.setTimestamp( position-1, (Date) value );
260+
nativeQuery.setTimestamp( position - 1, (Date) value );
243261
}
244262
}
245263
}
246264
else if ( Calendar.class.isInstance( value ) ) {
247265
if ( name != null ) {
248266
if ( specifiedTemporalType == DATE ) {
249-
query.setCalendarDate( name, (Calendar) value );
267+
nativeQuery.setCalendarDate( name, (Calendar) value );
250268
}
251269
else if ( specifiedTemporalType == TIME ) {
252270
throw new IllegalArgumentException( "not yet implemented" );
253271
}
254272
else if ( specifiedTemporalType == TIMESTAMP ) {
255-
query.setCalendar( name, (Calendar) value );
273+
nativeQuery.setCalendar( name, (Calendar) value );
256274
}
257275
}
258276
else {
259277
if ( specifiedTemporalType == DATE ) {
260-
query.setCalendarDate( position-1, (Calendar) value );
278+
nativeQuery.setCalendarDate( position - 1, (Calendar) value );
261279
}
262280
else if ( specifiedTemporalType == TIME ) {
263281
throw new IllegalArgumentException( "not yet implemented" );
264282
}
265283
else if ( specifiedTemporalType == TIMESTAMP ) {
266-
query.setCalendar( position-1, (Calendar) value );
284+
nativeQuery.setCalendar( position - 1, (Calendar) value );
267285
}
268286
}
269287
}

hibernate-entitymanager/src/main/java/org/hibernate/jpa/internal/StoredProcedureQueryImpl.java

Lines changed: 15 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,8 @@
4141
import org.hibernate.CacheMode;
4242
import org.hibernate.FlushMode;
4343
import org.hibernate.LockMode;
44+
import org.hibernate.jpa.spi.ParameterBind;
45+
import org.hibernate.jpa.spi.ParameterRegistration;
4446
import org.hibernate.procedure.NoSuchParameterException;
4547
import org.hibernate.procedure.ParameterStrategyException;
4648
import org.hibernate.procedure.ProcedureCall;
@@ -76,7 +78,7 @@ public StoredProcedureQueryImpl(ProcedureCallMemento memento, HibernateEntityMan
7678
super( entityManager );
7779
this.procedureCall = memento.makeProcedureCall( entityManager.getSession() );
7880
for ( org.hibernate.procedure.ParameterRegistration nativeParamReg : procedureCall.getRegisteredParameters() ) {
79-
registerParameter( new ParameterRegistrationImpl( nativeParamReg ) );
81+
registerParameter( new ParameterRegistrationImpl( this, nativeParamReg ) );
8082
}
8183
}
8284

@@ -122,6 +124,7 @@ public StoredProcedureQuery registerStoredProcedureParameter(int position, Class
122124
entityManager().checkOpen( true );
123125
registerParameter(
124126
new ParameterRegistrationImpl(
127+
this,
125128
procedureCall.registerParameter( position, type, mode )
126129
)
127130
);
@@ -134,6 +137,7 @@ public StoredProcedureQuery registerStoredProcedureParameter(String parameterNam
134137
entityManager().checkOpen( true );
135138
registerParameter(
136139
new ParameterRegistrationImpl(
140+
this,
137141
procedureCall.registerParameter( parameterName, type, mode )
138142
)
139143
);
@@ -407,11 +411,15 @@ public ProcedureCall getHibernateProcedureCall() {
407411
}
408412

409413
private static class ParameterRegistrationImpl<T> implements ParameterRegistration<T> {
414+
private final StoredProcedureQueryImpl query;
410415
private final org.hibernate.procedure.ParameterRegistration<T> nativeParamRegistration;
411416

412417
private ParameterBind<T> bind;
413418

414-
private ParameterRegistrationImpl(org.hibernate.procedure.ParameterRegistration<T> nativeParamRegistration) {
419+
public ParameterRegistrationImpl(
420+
StoredProcedureQueryImpl query,
421+
org.hibernate.procedure.ParameterRegistration<T> nativeParamRegistration) {
422+
this.query = query;
415423
this.nativeParamRegistration = nativeParamRegistration;
416424
}
417425

@@ -430,6 +438,11 @@ public Class<T> getParameterType() {
430438
return nativeParamRegistration.getType();
431439
}
432440

441+
@Override
442+
public Query getQuery() {
443+
return query;
444+
}
445+
433446
@Override
434447
public ParameterMode getMode() {
435448
return nativeParamRegistration.getMode();

hibernate-entitymanager/src/main/java/org/hibernate/jpa/spi/BaseQueryImpl.java

Lines changed: 6 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,6 @@
2727
import javax.persistence.CacheStoreMode;
2828
import javax.persistence.FlushModeType;
2929
import javax.persistence.Parameter;
30-
import javax.persistence.ParameterMode;
3130
import javax.persistence.Query;
3231
import javax.persistence.TemporalType;
3332
import java.util.Calendar;
@@ -409,7 +408,12 @@ public FlushModeType getFlushMode() {
409408

410409
protected <X> ParameterRegistration<X> findParameterRegistration(Parameter<X> parameter) {
411410
if ( ParameterRegistration.class.isInstance( parameter ) ) {
412-
return (ParameterRegistration<X>) parameter;
411+
final ParameterRegistration<X> reg = (ParameterRegistration<X>) parameter;
412+
// validate the parameter source
413+
if ( reg.getQuery() != this ) {
414+
throw new IllegalArgumentException( "Passed Parameter was from different Query" );
415+
}
416+
return reg;
413417
}
414418
else {
415419
if ( parameter.getName() != null ) {
@@ -440,45 +444,6 @@ protected <X> ParameterRegistration<X> findParameterRegistration(int parameterPo
440444

441445
protected abstract boolean isJpaPositionalParameter(int position);
442446

443-
/**
444-
* Hibernate specific extension to the JPA {@link javax.persistence.Parameter} contract. Used here to track
445-
* information known about the parameter.
446-
*/
447-
protected static interface ParameterRegistration<T> extends Parameter<T> {
448-
/**
449-
* Retrieves the parameter "mode" which describes how the parameter is defined in the actual database procedure
450-
* definition (is it an INPUT parameter? An OUTPUT parameter? etc).
451-
*
452-
* @return The parameter mode.
453-
*/
454-
public ParameterMode getMode();
455-
456-
/**
457-
* Can we bind (set) values on this parameter? Generally this is {@code true}, but would not be in the case
458-
* of parameters with OUT or REF_CURSOR mode.
459-
*
460-
* @return Whether the parameter is bindable (can set be called).
461-
*/
462-
public boolean isBindable();
463-
464-
public void bindValue(T value);
465-
466-
public void bindValue(T value, TemporalType specifiedTemporalType);
467-
468-
public ParameterBind<T> getBind();
469-
}
470-
471-
/**
472-
* Represents the value currently bound to a particular parameter.
473-
*
474-
* @param <T>
475-
*/
476-
protected static interface ParameterBind<T> {
477-
public T getValue();
478-
479-
public TemporalType getSpecifiedTemporalType();
480-
}
481-
482447
protected static class ParameterBindImpl<T> implements ParameterBind<T> {
483448
private final T value;
484449
private final TemporalType specifiedTemporalType;
Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
/*
2+
* Hibernate, Relational Persistence for Idiomatic Java
3+
*
4+
* Copyright (c) 2013, Red Hat Inc. or third-party contributors as
5+
* indicated by the @author tags or express copyright attribution
6+
* statements applied by the authors. All third-party contributions are
7+
* distributed under license by Red Hat Inc.
8+
*
9+
* This copyrighted material is made available to anyone wishing to use, modify,
10+
* copy, or redistribute it subject to the terms and conditions of the GNU
11+
* Lesser General Public License, as published by the Free Software Foundation.
12+
*
13+
* This program is distributed in the hope that it will be useful,
14+
* but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
15+
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
16+
* for more details.
17+
*
18+
* You should have received a copy of the GNU Lesser General Public License
19+
* along with this distribution; if not, write to:
20+
* Free Software Foundation, Inc.
21+
* 51 Franklin Street, Fifth Floor
22+
* Boston, MA 02110-1301 USA
23+
*/
24+
package org.hibernate.jpa.spi;
25+
26+
import javax.persistence.TemporalType;
27+
28+
/**
29+
* Represents the value currently bound to a particular (bindable) parameter.
30+
*
31+
* @param <T>
32+
*
33+
* @author Steve Ebersole
34+
*/
35+
public interface ParameterBind<T> {
36+
/**
37+
* Access the bound value
38+
*
39+
* @return The bound value
40+
*/
41+
public T getValue();
42+
43+
/**
44+
* The temporal type that will be used to "interpret" Date-like values (if applicable).
45+
*
46+
* @return The temporal type, or {@code null}
47+
*/
48+
public TemporalType getSpecifiedTemporalType();
49+
}

0 commit comments

Comments
 (0)