Docjar: A Java Source and Docuemnt Enginecom.*    java.*    javax.*    org.*    all    new    plug-in

Quick Search    Search Deep

Source code: org/hibernate/impl/AbstractQueryImpl.java


1   //$Id: AbstractQueryImpl.java,v 1.32 2005/04/13 07:37:49 oneovthafew Exp $
2   package org.hibernate.impl;
3   
4   import java.io.Serializable;
5   import java.math.BigDecimal;
6   import java.math.BigInteger;
7   import java.util.ArrayList;
8   import java.util.Arrays;
9   import java.util.Calendar;
10  import java.util.Collection;
11  import java.util.Date;
12  import java.util.HashMap;
13  import java.util.HashSet;
14  import java.util.Iterator;
15  import java.util.List;
16  import java.util.Locale;
17  import java.util.Map;
18  import java.util.Set;
19  import java.util.StringTokenizer;
20  
21  import org.hibernate.CacheMode;
22  import org.hibernate.FlushMode;
23  import org.hibernate.Hibernate;
24  import org.hibernate.HibernateException;
25  import org.hibernate.MappingException;
26  import org.hibernate.NonUniqueResultException;
27  import org.hibernate.PropertyNotFoundException;
28  import org.hibernate.Query;
29  import org.hibernate.QueryException;
30  import org.hibernate.engine.QueryParameters;
31  import org.hibernate.engine.RowSelection;
32  import org.hibernate.engine.SessionImplementor;
33  import org.hibernate.engine.TypedValue;
34  import org.hibernate.hql.classic.ParserHelper;
35  import org.hibernate.property.Getter;
36  import org.hibernate.proxy.HibernateProxyHelper;
37  import org.hibernate.type.SerializableType;
38  import org.hibernate.type.Type;
39  import org.hibernate.type.TypeFactory;
40  import org.hibernate.util.ArrayHelper;
41  import org.hibernate.util.MarkerObject;
42  import org.hibernate.util.ReflectHelper;
43  import org.hibernate.util.StringHelper;
44  
45  /**
46   * Abstract implementation of the Query interface
47   * @author Gavin King, Max Andersen
48   */
49  public abstract class AbstractQueryImpl implements Query {
50  
51    private static final Object UNSET_PARAMETER = new MarkerObject("<unset parameter>");
52    private static final Object UNSET_TYPE = new MarkerObject("<unset type>");
53  
54    private String queryString;
55    private final SessionImplementor session;
56  
57    private RowSelection selection;
58    private List values = new ArrayList(4);
59    private List types = new ArrayList(4);
60    private int positionalParameterCount = 0;
61    private Set actualNamedParameters = new HashSet(4);
62    private Map namedParameters = new HashMap(4);
63    private Map namedParameterLists = new HashMap(4);
64    private boolean cacheable;
65    private String cacheRegion;
66    private String comment;
67    private FlushMode flushMode;
68    private CacheMode cacheMode;
69    private FlushMode sessionFlushMode;
70    private CacheMode sessionCacheMode;
71    private Serializable collectionKey;
72    private boolean readOnly;
73  
74    public AbstractQueryImpl(String queryString, FlushMode flushMode, SessionImplementor session) {
75      this.session = session;
76      this.queryString = queryString;
77      this.selection = new RowSelection();
78      this.flushMode = flushMode;
79      this.cacheMode = null;
80      initParameterBookKeeping();
81    }
82  
83    public final String getQueryString() {
84      return queryString;
85    }
86    
87    public Query setFlushMode(FlushMode flushMode) {
88      this.flushMode = flushMode;
89      return this;
90    }
91    
92    public Query setCacheMode(CacheMode cacheMode) {
93      this.cacheMode = cacheMode;
94      return this;
95    }
96    
97    protected Map getNamedParams() {
98      return new HashMap(namedParameters);
99    }
100 
101   protected void verifyParameters() throws QueryException {
102     verifyParameters(false);
103   }
104   
105   /**
106    * @param reserveFirstParameter if true, the first ? will not be verified since its needed for e.g. callable statements returning a out parameter
107    * @throws HibernateException
108    */
109   protected void verifyParameters(boolean reserveFirstParameter) throws HibernateException {
110 
111     if ( actualNamedParameters.size() != namedParameters.size() + namedParameterLists.size() ) {
112       Set missingParams = new HashSet(actualNamedParameters);
113       missingParams.removeAll( namedParameterLists.keySet() );
114       missingParams.removeAll( namedParameters.keySet() );
115       throw new QueryException( "Not all named parameters have been set: " + missingParams, getQueryString() );
116     }
117     
118     int positionalValueSpan = 0;
119     for ( int i=0; i<values.size(); i++ ) {
120       Object object = types.get(i);
121       if( values.get(i)==UNSET_PARAMETER || object==UNSET_TYPE ) {
122         if(reserveFirstParameter && i==0) {
123           continue;
124         } else {
125           throw new QueryException( "Unset positional parameter at position: " + i, getQueryString() );
126         }
127       }
128       positionalValueSpan += ( (Type) object ).getColumnSpan( session.getFactory() );
129     }
130 
131     if ( positionalParameterCount!=positionalValueSpan ) {
132       if(reserveFirstParameter && positionalParameterCount-1!=positionalValueSpan) {
133         throw new QueryException( 
134              "Expected positional parameter count: " + 
135              (positionalParameterCount-1) + 
136              ", actual parameters: " + 
137              values, 
138              getQueryString() 
139          );
140       } else if (!reserveFirstParameter) {
141         throw new QueryException( 
142              "Expected positional parameter count: " + 
143              positionalParameterCount + 
144              ", actual parameters: " + 
145              values, 
146              getQueryString() 
147          );  
148       }      
149     }
150   }
151 
152   protected Map getNamedParameterLists() {
153     return namedParameterLists;
154   }
155 
156   protected List getValues() {
157     return values;
158   }
159 
160   protected List getTypes() {
161     return types;
162   }
163 
164   //TODO: maybe call it getRowSelection() ?
165   public RowSelection getSelection() {
166     return selection;
167   }
168 
169   public Query setMaxResults(int maxResults) {
170     selection.setMaxRows( new Integer(maxResults) );
171     return this;
172   }
173 
174   public Query setTimeout(int timeout) {
175     selection.setTimeout( new Integer(timeout) );
176     return this;
177   }
178   public Query setFetchSize(int fetchSize) {
179     selection.setFetchSize( new Integer(fetchSize) );
180     return this;
181   }
182 
183 
184   public Query setFirstResult(int firstResult) {
185     selection.setFirstRow( new Integer(firstResult) );
186     return this;
187   }
188 
189   public Query setParameter(int position, Object val, Type type) {
190     if ( positionalParameterCount==0 ) {
191       throw new IllegalArgumentException("No positional parameters in query: " + getQueryString() );
192     }
193     if ( position<0 || position>positionalParameterCount-1 ) {
194       throw new IllegalArgumentException("Positional parameter does not exist: " + position + " in query: " + getQueryString() );
195     }
196     int size = values.size();
197     if ( position<size ) {
198       values.set(position, val);
199       types.set(position, type);
200     }
201     else {
202       // prepend value and type list with null for any positions before the wanted position.
203       for ( int i=0; i<position-size; i++ ) {
204         values.add(UNSET_PARAMETER);
205         types.add(UNSET_TYPE);
206       }
207       values.add(val);
208       types.add(type);
209     }
210     return this;
211   }
212 
213   public Query setString(int position, String val) {
214     setParameter(position, val, Hibernate.STRING);
215     return this;
216   }
217 
218   public Query setCharacter(int position, char val) {
219     setParameter(position, new Character(val), Hibernate.CHARACTER);
220     return this;
221   }
222 
223   public Query setBoolean(int position, boolean val) {
224     setParameter(position, val ? Boolean.TRUE : Boolean.FALSE, Hibernate.BOOLEAN);
225     return this;
226   }
227 
228   public Query setByte(int position, byte val) {
229     setParameter(position, new Byte(val), Hibernate.BYTE);
230     return this;
231   }
232 
233   public Query setShort(int position, short val) {
234     setParameter(position, new Short(val), Hibernate.SHORT);
235     return this;
236   }
237 
238   public Query setInteger(int position, int val) {
239     setParameter(position, new Integer(val), Hibernate.INTEGER);
240     return this;
241   }
242 
243   public Query setLong(int position, long val) {
244     setParameter(position, new Long(val), Hibernate.LONG);
245     return this;
246   }
247 
248   public Query setFloat(int position, float val) {
249     setParameter(position, new Float(val), Hibernate.FLOAT);
250     return this;
251   }
252 
253   public Query setDouble(int position, double val) {
254     setParameter(position, new Double(val), Hibernate.DOUBLE);
255     return this;
256   }
257 
258   public Query setBinary(int position, byte[] val) {
259     setParameter(position, val, Hibernate.BINARY);
260     return this;
261   }
262 
263   public Query setText(int position, String val) {
264     setParameter(position, val, Hibernate.TEXT);
265     return this;
266   }
267 
268   public Query setSerializable(int position, Serializable val) {
269     setParameter(position, val, Hibernate.SERIALIZABLE);
270     return this;
271   }
272 
273   public Query setDate(int position, Date date) {
274     setParameter(position, date, Hibernate.DATE);
275     return this;
276   }
277 
278   public Query setTime(int position, Date date) {
279     setParameter(position, date, Hibernate.TIME);
280     return this;
281   }
282 
283   public Query setTimestamp(int position, Date date) {
284     setParameter(position, date, Hibernate.TIMESTAMP);
285     return this;
286   }
287 
288   public Query setEntity(int position, Object val) {
289     setParameter( position, val, Hibernate.entity( session.bestGuessEntityName(val) ) );
290     return this;
291   }
292 
293   public Query setLocale(int position, Locale locale) {
294     setParameter(position, locale, Hibernate.LOCALE);
295     return this;
296   }
297 
298   public Query setCalendar(int position, Calendar calendar) {
299     setParameter(position, calendar, Hibernate.CALENDAR);
300     return this;
301   }
302 
303   public Query setCalendarDate(int position, Calendar calendar) {
304     setParameter(position, calendar, Hibernate.CALENDAR_DATE);
305     return this;
306   }
307 
308   public Query setBinary(String name, byte[] val) {
309     setParameter(name, val, Hibernate.BINARY);
310     return this;
311   }
312 
313   public Query setText(String name, String val) {
314     setParameter(name, val, Hibernate.TEXT);
315     return this;
316   }
317 
318   public Query setBoolean(String name, boolean val) {
319     setParameter(name, val ? Boolean.TRUE : Boolean.FALSE, Hibernate.BOOLEAN);
320     return this;
321   }
322 
323   public Query setByte(String name, byte val) {
324     setParameter(name, new Byte(val), Hibernate.BYTE);
325     return this;
326   }
327 
328   public Query setCharacter(String name, char val) {
329     setParameter(name, new Character(val), Hibernate.CHARACTER);
330     return this;
331   }
332 
333   public Query setDate(String name, Date date) {
334     setParameter(name, date, Hibernate.DATE);
335     return this;
336   }
337 
338   public Query setDouble(String name, double val) {
339     setParameter(name, new Double(val), Hibernate.DOUBLE);
340     return this;
341   }
342 
343   public Query setEntity(String name, Object val) {
344     setParameter( name, val, Hibernate.entity( session.bestGuessEntityName(val) ) );
345     return this;
346   }
347 
348   public Query setFloat(String name, float val) {
349     setParameter(name, new Float(val), Hibernate.FLOAT);
350     return this;
351   }
352 
353   public Query setInteger(String name, int val) {
354     setParameter(name, new Integer(val), Hibernate.INTEGER);
355     return this;
356   }
357 
358   public Query setLocale(String name, Locale locale) {
359     setParameter(name, locale, Hibernate.LOCALE);
360     return this;
361   }
362 
363   public Query setCalendar(String name, Calendar calendar) {
364     setParameter(name, calendar, Hibernate.CALENDAR);
365     return this;
366   }
367 
368   public Query setCalendarDate(String name, Calendar calendar) {
369     setParameter(name, calendar, Hibernate.CALENDAR_DATE);
370     return this;
371   }
372 
373   public Query setLong(String name, long val) {
374     setParameter(name, new Long(val), Hibernate.LONG);
375     return this;
376   }
377 
378   public Query setParameter(String name, Object val, Type type) {
379     if( !actualNamedParameters.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 setSerializable(String name, Serializable val) {
389     setParameter(name, val, Hibernate.SERIALIZABLE);
390     return this;
391   }
392 
393   public Query setShort(String name, short val) {
394     setParameter(name, new Short(val), Hibernate.SHORT);
395     return this;
396   }
397 
398   public Query setString(String name, String val) {
399     setParameter(name, val, Hibernate.STRING);
400     return this;
401   }
402 
403   public Query setTime(String name, Date date) {
404     setParameter(name, date, Hibernate.TIME);
405     return this;
406   }
407 
408   public Query setTimestamp(String name, Date date) {
409     setParameter(name, date, Hibernate.TIMESTAMP);
410     return this;
411   }
412 
413   public Query setBigDecimal(int position, BigDecimal number) {
414     setParameter(position, number, Hibernate.BIG_DECIMAL);
415     return this;
416   }
417 
418   public Query setBigDecimal(String name, BigDecimal number) {
419     setParameter(name, number, Hibernate.BIG_DECIMAL);
420     return this;
421   }
422 
423   public Query setBigInteger(int position, BigInteger number) {
424     setParameter(position, number, Hibernate.BIG_DECIMAL);
425     return this;
426   }
427 
428   public Query setBigInteger(String name, BigInteger number) {
429     setParameter(name, number, Hibernate.BIG_DECIMAL);
430     return this;
431   }
432 
433   public Query setParameter(int position, Object val) throws HibernateException {
434     if (val == null) {
435       setParameter( position, val, Hibernate.SERIALIZABLE );
436     } 
437     else {
438       setParameter( position, val, guessType(val) );
439     }
440     return this;
441   }
442 
443   public Query setParameter(String name, Object val) throws HibernateException {
444     if (val == null) {
445       setParameter( name, val, Hibernate.SERIALIZABLE );
446     } 
447     else {
448       setParameter( name, val, guessType(val) );
449     }
450     return this;
451   }
452 
453   private Type guessType(Object param) throws HibernateException {
454     Class clazz = HibernateProxyHelper.getClassWithoutInitializingProxy(param);
455     return guessType(clazz);
456   }
457 
458   private Type guessType(Class clazz) throws HibernateException {
459     String typename = clazz.getName();
460     Type type = TypeFactory.heuristicType(typename);
461     boolean serializable = type!=null && type instanceof SerializableType;
462     if (type==null || serializable) {
463       try {
464         session.getFactory().getEntityPersister( clazz.getName() );
465       }
466       catch (MappingException me) {
467         if (serializable) {
468           return type;
469         }
470         else {
471           throw new HibernateException("Could not determine a type for class: " + typename);
472         }
473       }
474       return Hibernate.entity(clazz);
475     }
476     else {
477       return type;
478     }
479   }
480 
481 
482   public Type[] getReturnTypes() throws HibernateException {
483     return session.getFactory().getReturnTypes( queryString );
484   }
485 
486   public String[] getReturnAliases() throws HibernateException {
487     return session.getFactory().getReturnAliases( queryString );
488   }
489 
490   public Query setParameterList(String name, Collection vals, Type type) throws HibernateException {
491     if( !actualNamedParameters.contains(name) ) {
492          throw new IllegalArgumentException("Parameter " + name + " does not exist as a named parameter in [" + getQueryString() + "]");
493     }
494     namedParameterLists.put( name, new TypedValue( type, vals, session.getEntityMode() ) );
495     return this;
496   }
497   
498   /**
499    * Warning: adds new parameters to the argument by side-effect!
500    */
501   protected String bindParameterLists(Map namedParamsCopy) {
502     String query = this.queryString;
503     Iterator iter = namedParameterLists.entrySet().iterator();
504     while ( iter.hasNext() ) {
505       Map.Entry me = (Map.Entry) iter.next();
506       query = bindParameterList( query, (String) me.getKey(), (TypedValue) me.getValue(), namedParamsCopy );
507     }
508     return query;
509   }
510 
511   /**
512    * Warning: adds new parameters to the argument by side-effect!
513    */
514   private String bindParameterList(String query, String name, TypedValue typedList, Map namedParamsCopy) {
515     Collection vals = (Collection) typedList.getValue();
516     Type type = typedList.getType();
517     StringBuffer list = new StringBuffer(16);
518     Iterator iter = vals.iterator();
519     int i=0;
520     while ( iter.hasNext() ) {
521       String alias = name + i++ + '_';
522       namedParamsCopy.put(alias, new TypedValue( type, iter.next(), session.getEntityMode() ) );
523       list.append( ParserHelper.HQL_VARIABLE_PREFIX + alias );
524       if ( iter.hasNext() ) list.append(", ");
525     }
526     return StringHelper.replace( query, ParserHelper.HQL_VARIABLE_PREFIX + name, list.toString(), true );
527   }
528 
529   public Query setParameterList(String name, Collection vals) throws HibernateException {
530     if (vals==null) {
531       throw new QueryException("Collection must be not null!");
532     }
533 
534     if(vals.size()==0) {
535       setParameterList(name, vals, null);
536     }
537     else {
538       setParameterList(name, vals, guessType( vals.iterator().next() ) );
539     }
540 
541     return this;
542   }
543 
544   public String[] getNamedParameters() throws HibernateException {
545     return (String[]) actualNamedParameters.toArray(new String[actualNamedParameters.size()]);
546   }
547 
548   private void initParameterBookKeeping() {
549     StringTokenizer st = new StringTokenizer(queryString, ParserHelper.HQL_SEPARATORS);
550     Set result = new HashSet();
551 
552     while ( st.hasMoreTokens() ) {
553       String string = st.nextToken();
554       if( string.startsWith(ParserHelper.HQL_VARIABLE_PREFIX) ) {
555         result.add( string.substring(1) );
556       }
557     }
558 
559     actualNamedParameters = result;
560     positionalParameterCount = StringHelper.countUnquoted(queryString, '?');
561   }
562 
563   public Query setProperties(Object bean) throws HibernateException {
564     Class clazz = bean.getClass();
565     String[] params = getNamedParameters();
566     for (int i = 0; i < params.length; i++) {
567       String namedParam = params[i];
568       try {
569         Getter getter = ReflectHelper.getGetter(clazz, namedParam);
570         Class retType = getter.getReturnType();
571         final Object object = getter.get( bean );
572         if ( Collection.class.isAssignableFrom(retType) ) {
573           setParameterList( namedParam, (Collection) object );
574         }
575         else if ( retType.isArray() ) {
576            setParameterList( namedParam, (Object[]) object );
577         }
578         else {
579           setParameter( namedParam, object, guessType( getter.getReturnType() ) );
580         }
581       }
582       catch (PropertyNotFoundException pnfe) {}
583     }
584     return this;
585   }
586 
587 
588   public Query setParameterList(String name, Object[] vals, Type type)
589     throws HibernateException {
590     return setParameterList(name, Arrays.asList(vals), type);
591   }
592 
593   public Query setParameterList(String name, Object[] vals)
594     throws HibernateException {
595     return setParameterList( name, Arrays.asList(vals) );
596   }
597 
598   SessionImplementor getSession() {
599     return session;
600   }
601 
602   public Object uniqueResult() throws HibernateException {
603     return uniqueElement( list() );
604   }
605 
606   public int executeUpdate() throws HibernateException {
607     throw new UnsupportedOperationException( "Update queries only supported through HQL" );
608   }
609 
610   static Object uniqueElement(List list) throws NonUniqueResultException {
611     int size = list.size();
612     if (size==0) return null;
613     Object first = list.get(0);
614     for ( int i=1; i<size; i++ ) {
615       if ( list.get(i)!=first ) {
616         throw new NonUniqueResultException( list.size() );
617       }
618     }
619     return first;
620   }
621 
622   protected RowSelection getRowSelection() {
623     return selection;
624   }
625 
626   public Type[] typeArray() {
627     return ArrayHelper.toTypeArray( getTypes() );
628   }
629   
630   public Object[] valueArray() {
631     return getValues().toArray();
632   }
633 
634   public QueryParameters getQueryParameters(Map namedParams) {
635     return new QueryParameters(
636         typeArray(),
637         valueArray(),
638         namedParams,
639         getLockModes(),
640         getSelection(),
641         readOnly,
642         cacheable,
643         cacheRegion,
644         //forceCacheRefresh,
645         comment,
646         collectionKey==null ?
647             null :
648             new Serializable[] { collectionKey }
649     );
650   }
651   
652   protected abstract Map getLockModes();
653 
654   public Query setCacheable(boolean cacheable) {
655     this.cacheable = cacheable;
656     return this;
657   }
658 
659   public Query setCacheRegion(String cacheRegion) {
660     if (cacheRegion != null)
661       this.cacheRegion = cacheRegion.trim();
662     return this;
663   }
664 
665   public Query setComment(String comment) {
666     this.comment = comment;
667     return this;
668   }
669   
670   public String toString() {
671     return StringHelper.unqualify( getClass().getName() ) + '(' + queryString + ')';
672   }
673   
674   protected void before() {
675     if ( flushMode!=null ) {
676       sessionFlushMode = getSession().getFlushMode();
677       getSession().setFlushMode(flushMode);
678     }
679     if ( cacheMode!=null ) {
680       sessionCacheMode = getSession().getCacheMode();
681       getSession().setCacheMode(cacheMode);
682     }
683   }
684   
685   protected void after() {
686     if (sessionFlushMode!=null) {
687       getSession().setFlushMode(sessionFlushMode);
688       sessionFlushMode = null;
689     }
690     if (sessionCacheMode!=null) {
691       getSession().setCacheMode(sessionCacheMode);
692       sessionCacheMode = null;
693     }
694   }
695   
696   public Query setCollectionKey(Serializable collectionKey) {
697     this.collectionKey = collectionKey;
698     return this;
699   }
700   
701   public Query setParameters(Object[] values, Type[] types) {
702     this.values = Arrays.asList(values);
703     this.types = Arrays.asList(types);
704     return this;
705   }
706   
707   public boolean isReadOnly() {
708     return readOnly;
709   }
710   
711   public Query setReadOnly(boolean readOnly) {
712     this.readOnly = readOnly;
713     return this;
714   }
715 }