1 package org.hibernate.loader.hql; 3 4 import java.sql.PreparedStatement ; 5 import java.sql.ResultSet ; 6 import java.sql.SQLException ; 7 import java.util.HashMap ; 8 import java.util.Iterator ; 9 import java.util.List ; 10 import java.util.Map ; 11 12 import org.apache.commons.logging.Log; 13 import org.apache.commons.logging.LogFactory; 14 import org.hibernate.HibernateException; 15 import org.hibernate.LockMode; 16 import org.hibernate.QueryException; 17 import org.hibernate.ScrollableResults; 18 import org.hibernate.dialect.Dialect; 19 import org.hibernate.engine.QueryParameters; 20 import org.hibernate.engine.SessionFactoryImplementor; 21 import org.hibernate.engine.SessionImplementor; 22 import org.hibernate.engine.TypedValue; 23 import org.hibernate.event.EventSource; 24 import org.hibernate.exception.JDBCExceptionHelper; 25 import org.hibernate.hql.HolderInstantiator; 26 import org.hibernate.hql.QueryTranslator; 27 import org.hibernate.hql.ast.tree.FromElement; 28 import org.hibernate.hql.ast.tree.SelectClause; 29 import org.hibernate.impl.IteratorImpl; 30 import org.hibernate.loader.BasicLoader; 31 import org.hibernate.persister.collection.CollectionPersister; 32 import org.hibernate.persister.collection.QueryableCollection; 33 import org.hibernate.persister.entity.Loadable; 34 import org.hibernate.persister.entity.Queryable; 35 import org.hibernate.sql.ForUpdateFragment; 36 import org.hibernate.type.EntityType; 37 import org.hibernate.type.Type; 38 import org.hibernate.util.ArrayHelper; 39 40 47 public class QueryLoader extends BasicLoader { 48 49 private static final Log log = LogFactory.getLog( QueryLoader.class ); 50 53 private QueryTranslator queryTranslator; 54 55 private Queryable[] entityPersisters; 56 private String [] entityAliases; 57 private String [] sqlAliases; 58 private String [] sqlAliasSuffixes; 59 private boolean[] includeInSelect; 60 61 private String [] collectionSuffixes; 62 63 private boolean hasScalars; 64 private String [][] scalarColumnNames; 65 private Type[] queryReturnTypes; 67 68 private final Map sqlAliasByEntityAlias = new HashMap (8); 69 70 private EntityType[] ownerAssociationTypes; 71 private int[] owners; 72 private boolean[] entityEagerPropertyFetches; 73 74 private int[] collectionOwners; 75 private QueryableCollection[] collectionPersisters; 76 77 private int selectLength; 78 private HolderInstantiator holderInstantiator; 79 80 private LockMode[] defaultLockModes; 81 82 83 89 public QueryLoader(final QueryTranslator queryTranslator, 90 final SessionFactoryImplementor factory, 91 final SelectClause selectClause) { 92 super( factory ); 93 this.queryTranslator = queryTranslator; 94 initialize( selectClause ); 95 postInstantiate(); 96 } 97 98 private void initialize(SelectClause selectClause) { 99 100 List fromElementList = selectClause.getFromElementsForLoad(); 101 102 hasScalars = selectClause.isScalarSelect(); 103 scalarColumnNames = selectClause.getColumnNames(); 104 queryReturnTypes = selectClause.getQueryReturnTypes(); 106 107 holderInstantiator = new HolderInstantiator( 108 selectClause.getConstructor(), 109 selectClause.isMap(), 110 selectClause.isList(), 111 selectClause.getQueryReturnAliases() 112 ); 113 114 List collectionFromElements = selectClause.getCollectionFromElements(); 115 if ( collectionFromElements != null && collectionFromElements.size()!=0 ) { 116 int length = collectionFromElements.size(); 117 collectionPersisters = new QueryableCollection[length]; 118 collectionOwners = new int[length]; 119 collectionSuffixes = new String [length]; 120 for ( int i=0; i<length; i++ ) { 121 FromElement collectionFromElement = (FromElement) collectionFromElements.get(i); 122 collectionPersisters[i] = collectionFromElement.getQueryableCollection(); 123 collectionOwners[i] = fromElementList.indexOf( collectionFromElement.getOrigin() ); 124 collectionSuffixes[i] = collectionFromElement.getCollectionSuffix(); 127 } 128 } 129 130 int size = fromElementList.size(); 131 entityPersisters = new Queryable[size]; 132 entityEagerPropertyFetches = new boolean[size]; 133 entityAliases = new String [size]; 134 sqlAliases = new String [size]; 135 sqlAliasSuffixes = new String [size]; 136 includeInSelect = new boolean[size]; 137 owners = new int[size]; 138 ownerAssociationTypes = new EntityType[size]; 139 140 for ( int i = 0; i < size; i++ ) { 141 final FromElement element = ( FromElement ) fromElementList.get( i ); 142 entityPersisters[i] = ( Queryable ) element.getEntityPersister(); 143 144 if ( entityPersisters[i] == null ) { 145 throw new IllegalStateException ( "No entity persister for " + element.toString() ); 146 } 147 148 entityEagerPropertyFetches[i] = element.isAllPropertyFetch(); 149 sqlAliases[i] = element.getTableAlias(); 150 entityAliases[i] = element.getClassAlias(); 151 sqlAliasByEntityAlias.put( entityAliases[i], sqlAliases[i] ); 152 sqlAliasSuffixes[i] = ( size == 1 ) ? "" : Integer.toString( i ) + "_"; 154 includeInSelect[i] = !element.isFetch(); 156 if ( includeInSelect[i] ) selectLength++; 157 158 owners[i] = -1; if ( element.isFetch() ) { 160 if ( element.isCollectionJoin() || element.getQueryableCollection() != null ) { 161 } 163 else if ( element.getDataType().isEntityType() ) { 164 EntityType entityType = ( EntityType ) element.getDataType(); 165 if ( entityType.isOneToOne() ) { 166 owners[i] = fromElementList.indexOf( element.getOrigin() ); 167 } 168 ownerAssociationTypes[i] = entityType; 169 } 170 } 171 } 172 173 defaultLockModes = ArrayHelper.fillArray(LockMode.NONE, size); 175 176 } 177 178 180 public final void validateScrollability() throws HibernateException { 181 queryTranslator.validateScrollability(); 182 } 183 184 protected boolean needsFecthingScroll() { 185 return queryTranslator.containsCollectionFetches(); 186 } 187 188 public Loadable[] getEntityPersisters() { 189 return entityPersisters; 190 } 191 192 public String [] getAliases() { 193 return sqlAliases; 194 } 195 196 public String [] getSqlAliasSuffixes() { 197 return sqlAliasSuffixes; 198 } 199 200 public String [] getSuffixes() { 201 return getSqlAliasSuffixes(); 202 } 203 204 public String [] getCollectionSuffixes() { 205 return collectionSuffixes; 206 } 207 208 protected String getQueryIdentifier() { 209 return queryTranslator.getQueryString(); 210 } 211 212 215 protected String getSQLString() { 216 return queryTranslator.getSQLString(); 217 } 218 219 223 protected CollectionPersister[] getCollectionPersisters() { 224 return collectionPersisters; 225 } 226 227 protected int[] getCollectionOwners() { 228 return collectionOwners; 229 } 230 231 protected boolean[] getEntityEagerPropertyFetches() { 232 return entityEagerPropertyFetches; 233 } 234 235 239 protected int[] getOwners() { 240 return owners; 241 } 242 243 protected EntityType[] getOwnerAssociationTypes() { 244 return ownerAssociationTypes; 245 } 246 247 249 protected boolean isSubselectLoadingEnabled() { 250 return hasSubselectLoadableCollections(); 251 } 252 253 protected int bindNamedParameters(final PreparedStatement ps, 254 final Map namedParams, 255 final int start, 256 final SessionImplementor session) 257 throws SQLException , HibernateException { 258 259 if ( namedParams != null ) { 260 Iterator iter = namedParams.entrySet().iterator(); 262 int result = 0; 263 while ( iter.hasNext() ) { 264 Map.Entry e = ( Map.Entry ) iter.next(); 265 String name = ( String ) e.getKey(); 266 TypedValue typedval = ( TypedValue ) e.getValue(); 267 int[] locs = getNamedParameterLocs( name ); 268 for ( int i = 0; i < locs.length; i++ ) { 269 if ( log.isDebugEnabled() ) { 270 log.debug( "bindNamedParameters() " + 271 typedval.getValue() + " -> " + name + 272 " [" + ( locs[i] + start ) + "]" ); 273 } 274 typedval.getType().nullSafeSet( ps, typedval.getValue(), locs[i] + start, session ); 275 } 276 result += locs.length; 277 } 278 return result; 279 } 280 else { 281 return 0; 282 } 283 } 284 285 288 protected LockMode[] getLockModes(Map lockModes) { 289 290 if ( lockModes==null || lockModes.size()==0 ) { 291 return defaultLockModes; 292 } 293 else { 294 298 LockMode[] lockModeArray = new LockMode[entityAliases.length]; 299 for ( int i = 0; i < entityAliases.length; i++ ) { 300 LockMode lockMode = (LockMode) lockModes.get( entityAliases[i] ); 301 if ( lockMode == null ) { 302 lockMode = LockMode.NONE; 304 } 305 lockModeArray[i] = lockMode; 306 } 307 return lockModeArray; 308 } 309 } 310 311 protected String applyLocks(String sql, Map lockModes, Dialect dialect) 312 throws QueryException { 313 314 if ( lockModes == null || lockModes.size() == 0 ) { 315 return sql; 316 } 317 else { 318 320 final Map aliasedLockModes = new HashMap (); 323 final Iterator iter = lockModes.entrySet().iterator(); 324 while ( iter.hasNext() ) { 325 Map.Entry me = ( Map.Entry ) iter.next(); 326 final String userAlias = ( String ) me.getKey(); 327 final String sqlAlias = (String ) sqlAliasByEntityAlias.get( userAlias ); 328 if (sqlAlias==null) { 329 throw new IllegalArgumentException ("alias not found: " + userAlias); 330 } 331 aliasedLockModes.put( sqlAlias, me.getValue() ); 332 } 333 334 Map keyColumnNames = null; 336 if ( dialect.forUpdateOfColumns() ) { 337 final Loadable[] persisters = getEntityPersisters(); 338 keyColumnNames = new HashMap (); 339 for ( int i = 0; i < sqlAliases.length; i++ ) { 340 keyColumnNames.put( sqlAliases[i], persisters[i].getIdentifierColumnNames() ); 341 } 342 } 343 344 return sql + new ForUpdateFragment( dialect, aliasedLockModes, keyColumnNames ).toFragmentString(); 345 346 } 347 } 348 349 protected boolean upgradeLocks() { 350 return true; 351 } 352 353 protected Object getResultColumnOrRow(Object [] row, ResultSet rs, SessionImplementor session) 354 throws SQLException , HibernateException { 355 356 row = toResultRow( row ); 357 boolean isHolder = holderInstantiator.isRequired(); 358 if ( hasScalars ) { 359 String [][] scalarColumns = scalarColumnNames; 360 int queryCols = queryReturnTypes.length; 361 if ( !isHolder && queryCols == 1 ) { 362 return queryReturnTypes[0].nullSafeGet( rs, scalarColumns[0], session, null ); 363 } 364 else { 365 row = new Object [queryCols]; 366 for ( int i = 0; i < queryCols; i++ ) { 367 row[i] = queryReturnTypes[i].nullSafeGet( rs, scalarColumns[i], session, null ); 368 } 369 return row; 370 } 371 } 372 else if ( !isHolder ) { 373 return row.length == 1 ? row[0] : row; 374 } 375 else { 376 return row; 377 } 378 379 } 380 381 protected List getResultList(List results) throws QueryException { 382 if ( holderInstantiator.isRequired() ) { 384 for ( int i = 0; i < results.size(); i++ ) { 385 Object [] row = ( Object [] ) results.get( i ); 386 Object result = holderInstantiator.instantiate(row); 387 results.set( i, result ); 388 } 389 } 390 return results; 391 } 392 393 395 403 public List list(SessionImplementor session, QueryParameters queryParameters) 404 throws HibernateException { 405 return list( session, queryParameters, queryTranslator.getQuerySpaces(), queryReturnTypes ); 406 } 407 408 411 public Iterator iterate(QueryParameters queryParameters, EventSource session) 412 throws HibernateException { 413 414 final boolean stats = session.getFactory().getStatistics().isStatisticsEnabled(); 415 long startTime = 0; 416 if ( stats ) startTime = System.currentTimeMillis(); 417 418 try { 419 420 final PreparedStatement st = prepareQueryStatement( queryParameters, false, session ); 421 final ResultSet rs = getResultSet( st, queryParameters.getRowSelection(), session ); 422 final Iterator result = new IteratorImpl( 423 rs, 424 st, 425 session, 426 queryReturnTypes, 427 queryTranslator.getColumnNames(), 428 holderInstantiator 429 ); 430 431 if ( stats ) { 432 session.getFactory().getStatisticsImplementor().queryExecuted( 433 "HQL: " + queryTranslator.getQueryString(), 434 0, 435 System.currentTimeMillis() - startTime ); 436 } 437 438 return result; 439 440 } 441 catch ( SQLException sqle ) { 442 throw JDBCExceptionHelper.convert( 443 getFactory().getSQLExceptionConverter(), 444 sqle, 445 "could not execute query using iterate", 446 getSQLString() 447 ); 448 } 449 450 } 451 452 public ScrollableResults scroll(final QueryParameters queryParameters, 453 final SessionImplementor session) 454 throws HibernateException { 455 return scroll( queryParameters, queryReturnTypes, holderInstantiator, session ); 456 } 457 458 460 private Object [] toResultRow(Object [] row) { 461 if ( selectLength == row.length ) { 462 return row; 463 } 464 else { 465 Object [] result = new Object [selectLength]; 466 int j = 0; 467 for ( int i = 0; i < row.length; i++ ) { 468 if ( includeInSelect[i] ) result[j++] = row[i]; 469 } 470 return result; 471 } 472 } 473 474 477 private int[] getNamedParameterLocs(String name) throws QueryException { 478 return queryTranslator.getNamedParameterLocs( name ); 479 } 480 } 481
| Popular Tags
|