1 /*
2 * Hibernate, Relational Persistence for Idiomatic Java
3 *
4 * Copyright (c) 2008, Red Hat Middleware LLC 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 Middleware LLC.
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 */
25 package org.hibernate.impl;
26
27 import java.io.Serializable;
28 import java.math.BigDecimal;
29 import java.math.BigInteger;
30 import java.util.ArrayList;
31 import java.util.Arrays;
32 import java.util.Calendar;
33 import java.util.Collection;
34 import java.util.Date;
35 import java.util.HashMap;
36 import java.util.HashSet;
37 import java.util.Iterator;
38 import java.util.List;
39 import java.util.Locale;
40 import java.util.Map;
41 import java.util.Set;
42
43 import org.hibernate.CacheMode;
44 import org.hibernate.FlushMode;
45 import org.hibernate.Hibernate;
46 import org.hibernate.HibernateException;
47 import org.hibernate.MappingException;
48 import org.hibernate.NonUniqueResultException;
49 import org.hibernate.PropertyNotFoundException;
50 import org.hibernate.Query;
51 import org.hibernate.QueryException;
52 import org.hibernate.engine.QueryParameters;
53 import org.hibernate.engine.RowSelection;
54 import org.hibernate.engine.SessionImplementor;
55 import org.hibernate.engine.TypedValue;
56 import org.hibernate.engine.query.ParameterMetadata;
57 import org.hibernate.hql.classic.ParserHelper;
58 import org.hibernate.property.Getter;
59 import org.hibernate.proxy.HibernateProxyHelper;
60 import org.hibernate.transform.ResultTransformer;
61 import org.hibernate.type.SerializableType;
62 import org.hibernate.type.Type;
63 import org.hibernate.type.TypeFactory;
64 import org.hibernate.util.ArrayHelper;
65 import org.hibernate.util.MarkerObject;
66 import org.hibernate.util.ReflectHelper;
67 import org.hibernate.util.StringHelper;
68
69 /**
70 * Abstract implementation of the Query interface.
71 *
72 * @author Gavin King
73 * @author Max Andersen
74 */
75 public abstract class AbstractQueryImpl implements Query {
76
77 private static final Object UNSET_PARAMETER = new MarkerObject("<unset parameter>");
78 private static final Object UNSET_TYPE = new MarkerObject("<unset type>");
79
80 private final String queryString;
81 protected final SessionImplementor session;
82 protected final ParameterMetadata parameterMetadata;
83
84 // parameter bind values...
85 private List values = new ArrayList(4);
86 private List types = new ArrayList(4);
87 private Map namedParameters = new HashMap(4);
88 private Map namedParameterLists = new HashMap(4);
89
90 private Object optionalObject;
91 private Serializable optionalId;
92 private String optionalEntityName;
93
94 private RowSelection selection;
95 private boolean cacheable;
96 private String cacheRegion;
97 private String comment;
98 private FlushMode flushMode;
99 private CacheMode cacheMode;
100 private FlushMode sessionFlushMode;
101 private CacheMode sessionCacheMode;
102 private Serializable collectionKey;
103 private boolean readOnly;
104 private ResultTransformer resultTransformer;
105
106 public AbstractQueryImpl(
107 String queryString,
108 FlushMode flushMode,
109 SessionImplementor session,
110 ParameterMetadata parameterMetadata) {
111 this.session = session;
112 this.queryString = queryString;
113 this.selection = new RowSelection();
114 this.flushMode = flushMode;
115 this.cacheMode = null;
116 this.parameterMetadata = parameterMetadata;
117 }
118
119 public String toString() {
120 return StringHelper.unqualify( getClass().getName() ) + '(' + queryString + ')';
121 }
122
123 public final String getQueryString() {
124 return queryString;
125 }
126
127 //TODO: maybe call it getRowSelection() ?
128 public RowSelection getSelection() {
129 return selection;
130 }
131
132 public Query setFlushMode(FlushMode flushMode) {
133 this.flushMode = flushMode;
134 return this;
135 }
136
137 public Query setCacheMode(CacheMode cacheMode) {
138 this.cacheMode = cacheMode;
139 return this;
140 }
141
142 public Query setCacheable(boolean cacheable) {
143 this.cacheable = cacheable;
144 return this;
145 }
146
147 public Query setCacheRegion(String cacheRegion) {
148 if (cacheRegion != null)
149 this.cacheRegion = cacheRegion.trim();
150 return this;
151 }
152
153 public Query setComment(String comment) {
154 this.comment = comment;
155 return this;
156 }
157
158 public Query setFirstResult(int firstResult) {
159 selection.setFirstRow( new Integer(firstResult) );
160 return this;
161 }
162
163 public Query setMaxResults(int maxResults) {
164 selection.setMaxRows( new Integer(maxResults) );
165 return this;
166 }
167
168 public Query setTimeout(int timeout) {
169 selection.setTimeout( new Integer(timeout) );
170 return this;
171 }
172 public Query setFetchSize(int fetchSize) {
173 selection.setFetchSize( new Integer(fetchSize) );
174 return this;
175 }
176
177 public Type[] getReturnTypes() throws HibernateException {
178 return session.getFactory().getReturnTypes( queryString );
179 }
180
181 public String[] getReturnAliases() throws HibernateException {
182 return session.getFactory().getReturnAliases( queryString );
183 }
184
185 public Query setCollectionKey(Serializable collectionKey) {
186 this.collectionKey = collectionKey;
187 return this;
188 }
189
190 public boolean isReadOnly() {
191 return readOnly;
192 }
193
194 public Query setReadOnly(boolean readOnly) {
195 this.readOnly = readOnly;
196 return this;
197 }
198
199 public Query setResultTransformer(ResultTransformer transformer) {
200 this.resultTransformer = transformer;
201 return this;
202 }
203
204 public void setOptionalEntityName(String optionalEntityName) {
205 this.optionalEntityName = optionalEntityName;
206 }
207
208 public void setOptionalId(Serializable optionalId) {
209 this.optionalId = optionalId;
210 }
211
212 public void setOptionalObject(Object optionalObject) {
213 this.optionalObject = optionalObject;
214 }
215
216 SessionImplementor getSession() {
217 return session;
218 }
219
220 protected abstract Map getLockModes();
221
222
223 // Parameter handling code ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
224
225 /**
226 * Returns a shallow copy of the named parameter value map.
227 *
228 * @return Shallow copy of the named parameter value map
229 */
230 protected Map getNamedParams() {
231 return new HashMap( namedParameters );
232 }
233
234 /**
235 * Returns an array representing all named parameter names encountered
236 * during (intial) parsing of the query.
237 * <p/>
238 * Note <i>initial</i> here means different things depending on whether
239 * this is a native-sql query or an HQL/filter query. For native-sql, a
240 * precursory inspection of the query string is performed specifically to
241 * locate defined parameters. For HQL/filter queries, this is the
242 * information returned from the query-translator. This distinction
243 * holds true for all parameter metadata exposed here.
244 *
245 * @return Array of named parameter names.
246 * @throws HibernateException
247 */
248 public String[] getNamedParameters() throws HibernateException {
249 return ArrayHelper.toStringArray( parameterMetadata.getNamedParameterNames() );
250 }
251
252 /**
253 * Does this query contain named parameters?
254 *
255 * @return True if the query was found to contain named parameters; false
256 * otherwise;
257 */
258 public boolean hasNamedParameters() {
259 return parameterMetadata.getNamedParameterNames().size() > 0;
260 }
261
262 /**
263 * Retreive the value map for any named parameter lists (i.e., for
264 * auto-expansion) bound to this query.
265 *
266 * @return The parameter list value map.
267 */
268 protected Map getNamedParameterLists() {
269 return namedParameterLists;
270 }
271
272 /**
273 * Retreives the list of parameter values bound to this query for
274 * ordinal parameters.
275 *
276 * @return The ordinal parameter values.
277 */
278 protected List getValues() {
279 return values;
280 }
281
282 /**
283 * Retreives the list of parameter {@link Type type}s bound to this query for
284 * ordinal parameters.
285 *
286 * @return The ordinal parameter types.
287 */
288 protected List getTypes() {
289 return types;
290 }
291
292 /**
293 * Perform parameter validation. Used prior to executing the encapsulated
294 * query.
295 *
296 * @throws QueryException
297 */
298 protected void verifyParameters() throws QueryException {
299 verifyParameters(false);
300 }
301
302 /**
303 * Perform parameter validation. Used prior to executing the encapsulated
304 * query.
305 *
306 * @param reserveFirstParameter if true, the first ? will not be verified since
307 * its needed for e.g. callable statements returning a out parameter
308 * @throws HibernateException
309 */
310 protected void verifyParameters(boolean reserveFirstParameter) throws HibernateException {
311 if ( parameterMetadata.getNamedParameterNames().size() != namedParameters.size() + namedParameterLists.size() ) {
312 Set missingParams = new HashSet( parameterMetadata.getNamedParameterNames() );
313 missingParams.removeAll( namedParameterLists.keySet() );
314 missingParams.removeAll( namedParameters.keySet() );
315 throw new QueryException( "Not all named parameters have been set: " + missingParams, getQueryString() );
316 }
317
318 int positionalValueSpan = 0;
319 for ( int i = 0; i < values.size(); i++ ) {
320 Object object = types.get( i );
321 if( values.get( i ) == UNSET_PARAMETER || object == UNSET_TYPE ) {
322 if ( reserveFirstParameter && i==0 ) {
323 continue;
324 }
325 else {
326 throw new QueryException( "Unset positional parameter at position: " + i, getQueryString() );
327 }
328 }
329 positionalValueSpan += ( (Type) object ).getColumnSpan( session.getFactory() );
330 }
331
332 if ( parameterMetadata.getOrdinalParameterCount() != positionalValueSpan ) {
333 if ( reserveFirstParameter && parameterMetadata.getOrdinalParameterCount() - 1 != positionalValueSpan ) {
334 throw new QueryException(
335 "Expected positional parameter count: " +
336 (parameterMetadata.getOrdinalParameterCount()-1) +
337 ", actual parameters: " +
338 values,
339 getQueryString()
340 );
341 }
342 else if ( !reserveFirstParameter ) {
343 throw new QueryException(
344 "Expected positional parameter count: " +
345 parameterMetadata.getOrdinalParameterCount() +
346 ", actual parameters: " +
347 values,
348 getQueryString()
349 );
350 }
351 }
352 }
353
354 public Query setParameter(int position, Object val, Type type) {
355 if ( parameterMetadata.getOrdinalParameterCount() == 0 ) {
356 throw new IllegalArgumentException("No positional parameters in query: " + getQueryString() );
357 }
358 if ( position < 0 || position > parameterMetadata.getOrdinalParameterCount() - 1 ) {
359 throw new IllegalArgumentException("Positional parameter does not exist: " + position + " in query: " + getQueryString() );
360 }
361 int size = values.size();
362 if ( position < size ) {
363 values.set( position, val );
364 types.set( position, type );
365 }
366 else {
367 // prepend value and type list with null for any positions before the wanted position.
368 for ( int i = 0; i < position - size; i++ ) {
369 values.add( UNSET_PARAMETER );
370 types.add( UNSET_TYPE );
371 }
372 values.add( val );
373 types.add( type );
374 }
375 return this;
376 }
377
378 public Query setParameter(String name, Object val, Type type) {
379 if ( !parameterMetadata.getNamedParameterNames().contains( name ) ) {
380 throw new IllegalArgumentException("Parameter " + name + " does not exist as a named parameter in [" + getQueryString() + "]");
381 }
382 else {
383 namedParameters.put( name, new TypedValue( type, val, session.getEntityMode() ) );
384 return this;
385 }
386 }
387
388 public Query setParameter(int position, Object val) throws HibernateException {
389 if (val == null) {
390 setParameter( position, val, Hibernate.SERIALIZABLE );
391 }
392 else {
393 setParameter( position, val, determineType( position, val ) );
394 }
395 return this;
396 }
397
398 public Query setParameter(String name, Object val) throws HibernateException {
399 if (val == null) {
400 Type type = parameterMetadata.getNamedParameterExpectedType( name );
401 if ( type == null ) {
402 type = Hibernate.SERIALIZABLE;
403 }
404 setParameter( name, val, type );
405 }
406 else {
407 setParameter( name, val, determineType( name, val ) );
408 }
409 return this;
410 }
411
412 protected Type determineType(int paramPosition, Object paramValue, Type defaultType) {
413 Type type = parameterMetadata.getOrdinalParameterExpectedType( paramPosition + 1 );
414 if ( type == null ) {
415 type = defaultType;
416 }
417 return type;
418 }
419
420 protected Type determineType(int paramPosition, Object paramValue) throws HibernateException {
421 Type type = parameterMetadata.getOrdinalParameterExpectedType( paramPosition + 1 );
422 if ( type == null ) {
423 type = guessType( paramValue );
424 }
425 return type;
426 }
427
428 protected Type determineType(String paramName, Object paramValue, Type defaultType) {
429 Type type = parameterMetadata.getNamedParameterExpectedType( paramName );
430 if ( type == null ) {
431 type = defaultType;
432 }
433 return type;
434 }
435
436 protected Type determineType(String paramName, Object paramValue) throws HibernateException {
437 Type type = parameterMetadata.getNamedParameterExpectedType( paramName );
438 if ( type == null ) {
439 type = guessType( paramValue );
440 }
441 return type;
442 }
443
444 protected Type determineType(String paramName, Class clazz) throws HibernateException {
445 Type type = parameterMetadata.getNamedParameterExpectedType( paramName );
446 if ( type == null ) {
447 type = guessType( clazz );
448 }
449 return type;
450 }
451
452 private Type guessType(Object param) throws HibernateException {
453 Class clazz = HibernateProxyHelper.getClassWithoutInitializingProxy( param );
454 return guessType( clazz );
455 }
456
457 private Type guessType(Class clazz) throws HibernateException {
458 String typename = clazz.getName();
459 Type type = TypeFactory.heuristicType(typename);
460 boolean serializable = type!=null && type instanceof SerializableType;
461 if (type==null || serializable) {
462 try {
463 session.getFactory().getEntityPersister( clazz.getName() );
464 }
465 catch (MappingException me) {
466 if (serializable) {
467 return type;
468 }
469 else {
470 throw new HibernateException("Could not determine a type for class: " + typename);
471 }
472 }
473 return Hibernate.entity(clazz);
474 }
475 else {
476 return type;
477 }
478 }
479
480 public Query setString(int position, String val) {
481 setParameter(position, val, Hibernate.STRING);
482 return this;
483 }
484
485 public Query setCharacter(int position, char val) {
486 setParameter(position, new Character(val), Hibernate.CHARACTER);
487 return this;
488 }
489
490 public Query setBoolean(int position, boolean val) {
491 Boolean valueToUse = val ? Boolean.TRUE : Boolean.FALSE;
492 Type typeToUse = determineType( position, valueToUse, Hibernate.BOOLEAN );
493 setParameter( position, valueToUse, typeToUse );
494 return this;
495 }
496
497 public Query setByte(int position, byte val) {
498 setParameter(position, new Byte(val), Hibernate.BYTE);
499 return this;
500 }
501
502 public Query setShort(int position, short val) {
503 setParameter(position, new Short(val), Hibernate.SHORT);
504 return this;
505 }
506
507 public Query setInteger(int position, int val) {
508 setParameter(position, new Integer(val), Hibernate.INTEGER);
509 return this;
510 }
511
512 public Query setLong(int position, long val) {
513 setParameter(position, new Long(val), Hibernate.LONG);
514 return this;
515 }
516
517 public Query setFloat(int position, float val) {
518 setParameter(position, new Float(val), Hibernate.FLOAT);
519 return this;
520 }
521
522 public Query setDouble(int position, double val) {
523 setParameter(position, new Double(val), Hibernate.DOUBLE);
524 return this;
525 }
526
527 public Query setBinary(int position, byte[] val) {
528 setParameter(position, val, Hibernate.BINARY);
529 return this;
530 }
531
532 public Query setText(int position, String val) {
533 setParameter(position, val, Hibernate.TEXT);
534 return this;
535 }
536
537 public Query setSerializable(int position, Serializable val) {
538 setParameter(position, val, Hibernate.SERIALIZABLE);
539 return this;
540 }
541
542 public Query setDate(int position, Date date) {
543 setParameter(position, date, Hibernate.DATE);
544 return this;
545 }
546
547 public Query setTime(int position, Date date) {
548 setParameter(position, date, Hibernate.TIME);
549 return this;
550 }
551
552 public Query setTimestamp(int position, Date date) {
553 setParameter(position, date, Hibernate.TIMESTAMP);
554 return this;
555 }
556
557 public Query setEntity(int position, Object val) {
558 setParameter( position, val, Hibernate.entity( resolveEntityName( val ) ) );
559 return this;
560 }
561
562 private String resolveEntityName(Object val) {
563 if ( val == null ) {
564 throw new IllegalArgumentException( "entity for parameter binding cannot be null" );
565 }
566 return session.bestGuessEntityName( val );
567 }
568
569 public Query setLocale(int position, Locale locale) {
570 setParameter(position, locale, Hibernate.LOCALE);
571 return this;
572 }
573
574 public Query setCalendar(int position, Calendar calendar) {
575 setParameter(position, calendar, Hibernate.CALENDAR);
576 return this;
577 }
578
579 public Query setCalendarDate(int position, Calendar calendar) {
580 setParameter(position, calendar, Hibernate.CALENDAR_DATE);
581 return this;
582 }
583
584 public Query setBinary(String name, byte[] val) {
585 setParameter(name, val, Hibernate.BINARY);
586 return this;
587 }
588
589 public Query setText(String name, String val) {
590 setParameter(name, val, Hibernate.TEXT);
591 return this;
592 }
593
594 public Query setBoolean(String name, boolean val) {
595 Boolean valueToUse = val ? Boolean.TRUE : Boolean.FALSE;
596 Type typeToUse = determineType( name, valueToUse, Hibernate.BOOLEAN );
597 setParameter( name, valueToUse, typeToUse );
598 return this;
599 }
600
601 public Query setByte(String name, byte val) {
602 setParameter(name, new Byte(val), Hibernate.BYTE);
603 return this;
604 }
605
606 public Query setCharacter(String name, char val) {
607 setParameter(name, new Character(val), Hibernate.CHARACTER);
608 return this;
609 }
610
611 public Query setDate(String name, Date date) {
612 setParameter(name, date, Hibernate.DATE);
613 return this;
614 }
615
616 public Query setDouble(String name, double val) {
617 setParameter(name, new Double(val), Hibernate.DOUBLE);
618 return this;
619 }
620
621 public Query setEntity(String name, Object val) {
622 setParameter( name, val, Hibernate.entity( resolveEntityName( val ) ) );
623 return this;
624 }
625
626 public Query setFloat(String name, float val) {
627 setParameter(name, new Float(val), Hibernate.FLOAT);
628 return this;
629 }
630
631 public Query setInteger(String name, int val) {
632 setParameter(name, new Integer(val), Hibernate.INTEGER);
633 return this;
634 }
635
636 public Query setLocale(String name, Locale locale) {
637 setParameter(name, locale, Hibernate.LOCALE);
638 return this;
639 }
640
641 public Query setCalendar(String name, Calendar calendar) {
642 setParameter(name, calendar, Hibernate.CALENDAR);
643 return this;
644 }
645
646 public Query setCalendarDate(String name, Calendar calendar) {
647 setParameter(name, calendar, Hibernate.CALENDAR_DATE);
648 return this;
649 }
650
651 public Query setLong(String name, long val) {
652 setParameter(name, new Long(val), Hibernate.LONG);
653 return this;
654 }
655
656 public Query setSerializable(String name, Serializable val) {
657 setParameter(name, val, Hibernate.SERIALIZABLE);
658 return this;
659 }
660
661 public Query setShort(String name, short val) {
662 setParameter(name, new Short(val), Hibernate.SHORT);
663 return this;
664 }
665
666 public Query setString(String name, String val) {
667 setParameter(name, val, Hibernate.STRING);
668 return this;
669 }
670
671 public Query setTime(String name, Date date) {
672 setParameter(name, date, Hibernate.TIME);
673 return this;
674 }
675
676 public Query setTimestamp(String name, Date date) {
677 setParameter(name, date, Hibernate.TIMESTAMP);
678 return this;
679 }
680
681 public Query setBigDecimal(int position, BigDecimal number) {
682 setParameter(position, number, Hibernate.BIG_DECIMAL);
683 return this;
684 }
685
686 public Query setBigDecimal(String name, BigDecimal number) {
687 setParameter(name, number, Hibernate.BIG_DECIMAL);
688 return this;
689 }
690
691 public Query setBigInteger(int position, BigInteger number) {
692 setParameter(position, number, Hibernate.BIG_INTEGER);
693 return this;
694 }
695
696 public Query setBigInteger(String name, BigInteger number) {
697 setParameter(name, number, Hibernate.BIG_INTEGER);
698 return this;
699 }
700
701 public Query setParameterList(String name, Collection vals, Type type) throws HibernateException {
702 if ( !parameterMetadata.getNamedParameterNames().contains( name ) ) {
703 throw new IllegalArgumentException("Parameter " + name + " does not exist as a named parameter in [" + getQueryString() + "]");
704 }
705 namedParameterLists.put( name, new TypedValue( type, vals, session.getEntityMode() ) );
706 return this;
707 }
708
709 /**
710 * Warning: adds new parameters to the argument by side-effect, as well as
711 * mutating the query string!
712 */
713 protected String expandParameterLists(Map namedParamsCopy) {
714 String query = this.queryString;
715 Iterator iter = namedParameterLists.entrySet().iterator();
716 while ( iter.hasNext() ) {
717 Map.Entry me = (Map.Entry) iter.next();
718 query = expandParameterList( query, (String) me.getKey(), (TypedValue) me.getValue(), namedParamsCopy );
719 }
720 return query;
721 }
722
723 /**
724 * Warning: adds new parameters to the argument by side-effect, as well as
725 * mutating the query string!
726 */
727 private String expandParameterList(String query, String name, TypedValue typedList, Map namedParamsCopy) {
728 Collection vals = (Collection) typedList.getValue();
729 Type type = typedList.getType();
730 if ( vals.size() == 1 ) {
731 // short-circuit for performance...
732 namedParamsCopy.put( name, new TypedValue( type, vals.iterator().next(), session.getEntityMode() ) );
733 return query;
734 }
735
736 StringBuffer list = new StringBuffer( 16 );
737 Iterator iter = vals.iterator();
738 int i = 0;
739 boolean isJpaPositionalParam = parameterMetadata.getNamedParameterDescriptor( name ).isJpaStyle();
740 while ( iter.hasNext() ) {
741 String alias = ( isJpaPositionalParam ? 'x' + name : name ) + i++ + '_';
742 namedParamsCopy.put( alias, new TypedValue( type, iter.next(), session.getEntityMode() ) );
743 list.append( ParserHelper.HQL_VARIABLE_PREFIX ).append( alias );
744 if ( iter.hasNext() ) {
745 list.append( ", " );
746 }
747 }
748 String paramPrefix = isJpaPositionalParam ? "?" : ParserHelper.HQL_VARIABLE_PREFIX;
749 return StringHelper.replace( query, paramPrefix + name, list.toString(), true );
750 }
751
752 public Query setParameterList(String name, Collection vals) throws HibernateException {
753 if ( vals == null ) {
754 throw new QueryException( "Collection must be not null!" );
755 }
756
757 if( vals.size() == 0 ) {
758 setParameterList( name, vals, null );
759 }
760 else {
761 setParameterList(name, vals, determineType( name, vals.iterator().next() ) );
762 }
763
764 return this;
765 }
766
767 public Query setParameterList(String name, Object[] vals, Type type) throws HibernateException {
768 return setParameterList( name, Arrays.asList(vals), type );
769 }
770
771 public Query setParameterList(String name, Object[] vals) throws HibernateException {
772 return setParameterList( name, Arrays.asList(vals) );
773 }
774
775 public Query setProperties(Map map) throws HibernateException {
776 String[] params = getNamedParameters();
777 for (int i = 0; i < params.length; i++) {
778 String namedParam = params[i];
779 final Object object = map.get(namedParam);
780 if(object==null) {
781 continue;
782 }
783 Class retType = object.getClass();
784 if ( Collection.class.isAssignableFrom( retType ) ) {
785 setParameterList( namedParam, ( Collection ) object );
786 }
787 else if ( retType.isArray() ) {
788 setParameterList( namedParam, ( Object[] ) object );
789 }
790 else {
791 setParameter( namedParam, object, determineType( namedParam, retType ) );
792 }
793
794
795 }
796 return this;
797 }
798
799 public Query setProperties(Object bean) throws HibernateException {
800 Class clazz = bean.getClass();
801 String[] params = getNamedParameters();
802 for (int i = 0; i < params.length; i++) {
803 String namedParam = params[i];
804 try {
805 Getter getter = ReflectHelper.getGetter( clazz, namedParam );
806 Class retType = getter.getReturnType();
807 final Object object = getter.get( bean );
808 if ( Collection.class.isAssignableFrom( retType ) ) {
809 setParameterList( namedParam, ( Collection ) object );
810 }
811 else if ( retType.isArray() ) {
812 setParameterList( namedParam, ( Object[] ) object );
813 }
814 else {
815 setParameter( namedParam, object, determineType( namedParam, retType ) );
816 }
817 }
818 catch (PropertyNotFoundException pnfe) {
819 // ignore
820 }
821 }
822 return this;
823 }
824
825 public Query setParameters(Object[] values, Type[] types) {
826 this.values = Arrays.asList(values);
827 this.types = Arrays.asList(types);
828 return this;
829 }
830
831
832 // Execution methods ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
833
834 public Object uniqueResult() throws HibernateException {
835 return uniqueElement( list() );
836 }
837
838 static Object uniqueElement(List list) throws NonUniqueResultException {
839 int size = list.size();
840 if (size==0) return null;
841 Object first = list.get(0);
842 for ( int i=1; i<size; i++ ) {
843 if ( list.get(i)!=first ) {
844 throw new NonUniqueResultException( list.size() );
845 }
846 }
847 return first;
848 }
849
850 protected RowSelection getRowSelection() {
851 return selection;
852 }
853
854 public Type[] typeArray() {
855 return ArrayHelper.toTypeArray( getTypes() );
856 }
857
858 public Object[] valueArray() {
859 return getValues().toArray();
860 }
861
862 public QueryParameters getQueryParameters(Map namedParams) {
863 return new QueryParameters(
864 typeArray(),
865 valueArray(),
866 namedParams,
867 getLockModes(),
868 getSelection(),
869 readOnly,
870 cacheable,
871 cacheRegion,
872 comment,
873 collectionKey == null ? null : new Serializable[] { collectionKey },
874 optionalObject,
875 optionalEntityName,
876 optionalId,
877 resultTransformer
878 );
879 }
880
881 protected void before() {
882 if ( flushMode!=null ) {
883 sessionFlushMode = getSession().getFlushMode();
884 getSession().setFlushMode(flushMode);
885 }
886 if ( cacheMode!=null ) {
887 sessionCacheMode = getSession().getCacheMode();
888 getSession().setCacheMode(cacheMode);
889 }
890 }
891
892 protected void after() {
893 if (sessionFlushMode!=null) {
894 getSession().setFlushMode(sessionFlushMode);
895 sessionFlushMode = null;
896 }
897 if (sessionCacheMode!=null) {
898 getSession().setCacheMode(sessionCacheMode);
899 sessionCacheMode = null;
900 }
901 }
902 }