1 package org.hibernate.hql.classic; 3 4 import java.io.Serializable ; 5 import java.lang.reflect.Constructor ; 6 import java.sql.PreparedStatement ; 7 import java.sql.ResultSet ; 8 import java.sql.SQLException ; 9 import java.util.ArrayList ; 10 import java.util.HashMap ; 11 import java.util.HashSet ; 12 import java.util.Iterator ; 13 import java.util.List ; 14 import java.util.Map ; 15 import java.util.Set ; 16 17 import org.apache.commons.collections.SequencedHashMap; 18 import org.apache.commons.logging.Log; 19 import org.apache.commons.logging.LogFactory; 20 import org.hibernate.HibernateException; 21 import org.hibernate.LockMode; 22 import org.hibernate.MappingException; 23 import org.hibernate.QueryException; 24 import org.hibernate.ScrollableResults; 25 import org.hibernate.dialect.Dialect; 26 import org.hibernate.engine.JoinSequence; 27 import org.hibernate.engine.QueryParameters; 28 import org.hibernate.engine.SessionFactoryImplementor; 29 import org.hibernate.engine.SessionImplementor; 30 import org.hibernate.engine.TypedValue; 31 import org.hibernate.event.EventSource; 32 import org.hibernate.exception.JDBCExceptionHelper; 33 import org.hibernate.hql.FilterTranslator; 34 import org.hibernate.hql.HolderInstantiator; 35 import org.hibernate.hql.NameGenerator; 36 import org.hibernate.hql.QueryTranslator; 37 import org.hibernate.impl.IteratorImpl; 38 import org.hibernate.loader.BasicLoader; 39 import org.hibernate.persister.collection.CollectionPersister; 40 import org.hibernate.persister.collection.QueryableCollection; 41 import org.hibernate.persister.entity.Loadable; 42 import org.hibernate.persister.entity.PropertyMapping; 43 import org.hibernate.persister.entity.Queryable; 44 import org.hibernate.sql.ForUpdateFragment; 45 import org.hibernate.sql.JoinFragment; 46 import org.hibernate.sql.QuerySelect; 47 import org.hibernate.type.AssociationType; 48 import org.hibernate.type.EntityType; 49 import org.hibernate.type.Type; 50 import org.hibernate.type.TypeFactory; 51 import org.hibernate.util.ArrayHelper; 52 import org.hibernate.util.ReflectHelper; 53 import org.hibernate.util.StringHelper; 54 55 59 public class QueryTranslatorImpl extends BasicLoader 60 implements QueryTranslator, FilterTranslator { 61 62 private final String queryString; 63 64 private final Map typeMap = new SequencedHashMap(); 65 private final Map collections = new SequencedHashMap(); 66 private List returnedTypes = new ArrayList (); 67 private final List fromTypes = new ArrayList (); 68 private final List scalarTypes = new ArrayList (); 69 private final Map namedParameters = new HashMap (); 70 private final Map aliasNames = new HashMap (); 71 private final Map oneToOneOwnerNames = new HashMap (); 72 private final Map uniqueKeyOwnerReferences = new HashMap (); 73 private final Map decoratedPropertyMappings = new HashMap (); 74 75 private final List scalarSelectTokens = new ArrayList (); 76 private final List whereTokens = new ArrayList (); 77 private final List havingTokens = new ArrayList (); 78 private final Map joins = new SequencedHashMap(); 79 private final List orderByTokens = new ArrayList (); 80 private final List groupByTokens = new ArrayList (); 81 private final Set querySpaces = new HashSet (); 82 private final Set entitiesToFetch = new HashSet (); 83 84 private final Map pathAliases = new HashMap (); 85 private final Map pathJoins = new HashMap (); 86 87 private Queryable[] persisters; 88 private int[] owners; 89 private EntityType[] ownerAssociationTypes; 90 private String [] names; 91 private boolean[] includeInSelect; 92 private int selectLength; 93 private Type[] returnTypes; 94 private Type[] actualReturnTypes; 95 private String [][] scalarColumnNames; 96 private Map tokenReplacements; 97 private int nameCount = 0; 98 private int parameterCount = 0; 99 private boolean distinct = false; 100 private boolean compiled; 101 private String sqlString; 102 private Class holderClass; 103 private Constructor holderConstructor; 104 private boolean hasScalars; 105 private boolean shallowQuery; 106 private QueryTranslatorImpl superQuery; 107 108 private QueryableCollection collectionPersister; 109 private int collectionOwnerColumn = -1; 110 private String collectionOwnerName; 111 private String fetchName; 112 113 private String [] suffixes; 114 115 private Map enabledFilters; 116 117 private static final Log log = LogFactory.getLog( QueryTranslatorImpl.class ); 118 119 122 public QueryTranslatorImpl( 123 String queryString, 124 Map enabledFilters, 125 SessionFactoryImplementor factory) { 126 super( factory ); 127 this.queryString = queryString; 128 this.enabledFilters = enabledFilters; 129 } 130 131 134 void compile(QueryTranslatorImpl superquery) 135 throws QueryException, MappingException { 136 this.tokenReplacements = superquery.tokenReplacements; 137 this.superQuery = superquery; 138 this.shallowQuery = true; 139 this.enabledFilters = superquery.getEnabledFilters(); 140 compile(); 141 } 142 143 144 148 public synchronized void compile(Map replacements, boolean scalar) 149 throws QueryException, MappingException { 150 if ( !compiled ) { 151 this.tokenReplacements = replacements; 152 this.shallowQuery = scalar; 153 compile(); 154 } 155 } 156 157 161 public synchronized void compile(String collectionRole, Map replacements, boolean scalar) 162 throws QueryException, MappingException { 163 164 if ( !isCompiled() ) { 165 addFromAssociation( "this", collectionRole ); 166 compile( replacements, scalar ); 167 } 168 } 169 170 173 private void compile() throws QueryException, MappingException { 174 175 log.trace( "compiling query" ); 176 try { 177 ParserHelper.parse( new PreprocessingParser( tokenReplacements ), 178 queryString, 179 ParserHelper.HQL_SEPARATORS, 180 this ); 181 renderSQL(); 182 } 183 catch ( QueryException qe ) { 184 qe.setQueryString( queryString ); 185 throw qe; 186 } 187 catch ( MappingException me ) { 188 throw me; 189 } 190 catch ( Exception e ) { 191 log.debug( "unexpected query compilation problem", e ); 192 e.printStackTrace(); 193 QueryException qe = new QueryException( "Incorrect query syntax", e ); 194 qe.setQueryString( queryString ); 195 throw qe; 196 } 197 198 postInstantiate(); 199 200 compiled = true; 201 202 } 203 204 public String getSQLString() { 205 return sqlString; 206 } 207 208 public String getQueryString() { 209 return queryString; 210 } 211 212 217 protected Loadable[] getEntityPersisters() { 218 return persisters; 219 } 220 221 226 public Type[] getReturnTypes() { 227 return actualReturnTypes; 228 } 229 230 public String [] getReturnAliases() { 231 throw new UnsupportedOperationException ("select clause aliases are not supported by classic parser"); 232 } 233 234 public String [][] getColumnNames() { 235 return scalarColumnNames; 236 } 237 238 private static void logQuery(String hql, String sql) { 239 if ( log.isDebugEnabled() ) { 240 log.debug( "HQL: " + hql ); 241 log.debug( "SQL: " + sql ); 242 } 243 } 244 245 void setAliasName(String alias, String name) { 246 aliasNames.put( alias, name ); 247 } 248 249 public String getAliasName(String alias) { 250 String name = ( String ) aliasNames.get( alias ); 251 if ( name == null ) { 252 if ( superQuery != null ) { 253 name = superQuery.getAliasName( alias ); 254 } 255 else { 256 name = alias; 257 } 258 } 259 return name; 260 } 261 262 String unalias(String path) { 263 String alias = StringHelper.root( path ); 264 String name = getAliasName( alias ); 265 if ( name != null ) { 266 return name + path.substring( alias.length() ); 267 } 268 else { 269 return path; 270 } 271 } 272 273 void addEntityToFetch(String name, String oneToOneOwnerName, AssociationType ownerAssociationType) { 274 addEntityToFetch( name ); 275 if ( oneToOneOwnerName != null ) oneToOneOwnerNames.put( name, oneToOneOwnerName ); 276 if ( ownerAssociationType != null ) uniqueKeyOwnerReferences.put( name, ownerAssociationType ); 277 } 278 279 private void addEntityToFetch(String name) { 280 entitiesToFetch.add( name ); 281 } 282 283 private int nextCount() { 284 return ( superQuery == null ) ? nameCount++ : superQuery.nameCount++; 285 } 286 287 String createNameFor(String type) { 288 return StringHelper.generateAlias( type, nextCount() ); 289 } 290 291 String createNameForCollection(String role) { 292 return StringHelper.generateAlias( role, nextCount() ); 293 } 294 295 private String getType(String name) { 296 String type = ( String ) typeMap.get( name ); 297 if ( type == null && superQuery != null ) { 298 type = superQuery.getType( name ); 299 } 300 return type; 301 } 302 303 private String getRole(String name) { 304 String role = ( String ) collections.get( name ); 305 if ( role == null && superQuery != null ) { 306 role = superQuery.getRole( name ); 307 } 308 return role; 309 } 310 311 boolean isName(String name) { 312 return aliasNames.containsKey( name ) || 313 typeMap.containsKey( name ) || 314 collections.containsKey( name ) || ( 315 superQuery != null && superQuery.isName( name ) 316 ); 317 } 318 319 PropertyMapping getPropertyMapping(String name) throws QueryException { 320 PropertyMapping decorator = getDecoratedPropertyMapping( name ); 321 if ( decorator != null ) return decorator; 322 323 String type = getType( name ); 324 if ( type == null ) { 325 String role = getRole( name ); 326 if ( role == null ) { 327 throw new QueryException( "alias not found: " + name ); 328 } 329 return getCollectionPersister( role ); } 331 else { 332 Queryable persister = getEntityPersister( type ); 333 if ( persister == null ) throw new QueryException( "persistent class not found: " + type ); 334 return persister; 335 } 336 } 337 338 private PropertyMapping getDecoratedPropertyMapping(String name) { 339 return ( PropertyMapping ) decoratedPropertyMappings.get( name ); 340 } 341 342 void decoratePropertyMapping(String name, PropertyMapping mapping) { 343 decoratedPropertyMappings.put( name, mapping ); 344 } 345 346 private Queryable getEntityPersisterForName(String name) throws QueryException { 347 String type = getType( name ); 348 Queryable persister = getEntityPersister( type ); 349 if ( persister == null ) throw new QueryException( "persistent class not found: " + type ); 350 return persister; 351 } 352 353 Queryable getEntityPersisterUsingImports(String className) { 354 final String importedClassName = getFactory().getImportedClassName( className ); 355 if ( importedClassName == null ) { 356 return null; 357 } 358 try { 359 return ( Queryable ) getFactory().getEntityPersister( importedClassName ); 360 } 361 catch ( MappingException me ) { 362 return null; 363 } 364 } 365 366 Queryable getEntityPersister(String entityName) throws QueryException { 367 try { 368 return ( Queryable ) getFactory().getEntityPersister( entityName ); 369 } 370 catch ( Exception e ) { 371 throw new QueryException( "persistent class not found: " + entityName ); 372 } 373 } 374 375 QueryableCollection getCollectionPersister(String role) throws QueryException { 376 try { 377 return ( QueryableCollection ) getFactory().getCollectionPersister( role ); 378 } 379 catch ( ClassCastException cce ) { 380 throw new QueryException( "collection role is not queryable: " + role ); 381 } 382 catch ( Exception e ) { 383 throw new QueryException( "collection role not found: " + role ); 384 } 385 } 386 387 void addType(String name, String type) { 388 typeMap.put( name, type ); 389 } 390 391 void addCollection(String name, String role) { 392 collections.put( name, role ); 393 } 394 395 void addFrom(String name, String type, JoinSequence joinSequence) 396 throws QueryException { 397 addType( name, type ); 398 addFrom( name, joinSequence ); 399 } 400 401 void addFromCollection(String name, String collectionRole, JoinSequence joinSequence) 402 throws QueryException { 403 addCollection( name, collectionRole ); 405 addJoin( name, joinSequence ); 406 } 407 408 void addFrom(String name, JoinSequence joinSequence) 409 throws QueryException { 410 fromTypes.add( name ); 411 addJoin( name, joinSequence ); 412 } 413 414 void addFromClass(String name, Queryable classPersister) 415 throws QueryException { 416 JoinSequence joinSequence = new JoinSequence( getFactory() ) 417 .setRoot( classPersister, name ); 418 addFrom( name, classPersister.getEntityName(), joinSequence ); 420 } 421 422 void addSelectClass(String name) { 423 returnedTypes.add( name ); 424 } 425 426 void addSelectScalar(Type type) { 427 scalarTypes.add( type ); 428 } 429 430 void appendWhereToken(String token) { 431 whereTokens.add( token ); 432 } 433 434 void appendHavingToken(String token) { 435 havingTokens.add( token ); 436 } 437 438 void appendOrderByToken(String token) { 439 orderByTokens.add( token ); 440 } 441 442 void appendGroupByToken(String token) { 443 groupByTokens.add( token ); 444 } 445 446 void appendScalarSelectToken(String token) { 447 scalarSelectTokens.add( token ); 448 } 449 450 void appendScalarSelectTokens(String [] tokens) { 451 scalarSelectTokens.add( tokens ); 452 } 453 454 void addFromJoinOnly(String name, JoinSequence joinSequence) throws QueryException { 455 addJoin( name, joinSequence.getFromPart() ); 456 } 457 458 void addJoin(String name, JoinSequence joinSequence) throws QueryException { 459 if ( !joins.containsKey( name ) ) joins.put( name, joinSequence ); 460 } 461 462 void addNamedParameter(String name) { 463 if ( superQuery != null ) superQuery.addNamedParameter( name ); 464 Integer loc = new Integer ( parameterCount++ ); 465 Object o = namedParameters.get( name ); 466 if ( o == null ) { 467 namedParameters.put( name, loc ); 468 } 469 else if ( o instanceof Integer ) { 470 ArrayList list = new ArrayList ( 4 ); 471 list.add( o ); 472 list.add( loc ); 473 namedParameters.put( name, list ); 474 } 475 else { 476 ( ( ArrayList ) o ).add( loc ); 477 } 478 } 479 480 public int[] getNamedParameterLocs(String name) throws QueryException { 481 Object o = namedParameters.get( name ); 482 if ( o == null ) { 483 QueryException qe = new QueryException( ERROR_NAMED_PARAMETER_DOES_NOT_APPEAR + name ); 484 qe.setQueryString( queryString ); 485 throw qe; 486 } 487 if ( o instanceof Integer ) { 488 return new int[]{( ( Integer ) o ).intValue()}; 489 } 490 else { 491 return ArrayHelper.toIntArray( ( ArrayList ) o ); 492 } 493 } 494 495 private void renderSQL() throws QueryException, MappingException { 496 497 final int rtsize; 498 if ( returnedTypes.size() == 0 && scalarTypes.size() == 0 ) { 499 returnedTypes = fromTypes; 501 rtsize = returnedTypes.size(); 502 } 503 else { 504 rtsize = returnedTypes.size(); 505 Iterator iter = entitiesToFetch.iterator(); 506 while ( iter.hasNext() ) { 507 returnedTypes.add( iter.next() ); 508 } 509 } 510 int size = returnedTypes.size(); 511 persisters = new Queryable[size]; 512 names = new String [size]; 513 owners = new int[size]; 514 ownerAssociationTypes = new EntityType[size]; 515 suffixes = new String [size]; 516 includeInSelect = new boolean[size]; 517 for ( int i = 0; i < size; i++ ) { 518 String name = ( String ) returnedTypes.get( i ); 519 persisters[i] = getEntityPersisterForName( name ); 521 suffixes[i] = ( size == 1 ) ? "" : Integer.toString( i ) + '_'; 523 names[i] = name; 524 includeInSelect[i] = !entitiesToFetch.contains( name ); 525 if ( includeInSelect[i] ) selectLength++; 526 if ( name.equals( collectionOwnerName ) ) collectionOwnerColumn = i; 527 String oneToOneOwner = ( String ) oneToOneOwnerNames.get( name ); 528 owners[i] = ( oneToOneOwner == null ) ? -1 : returnedTypes.indexOf( oneToOneOwner ); 529 ownerAssociationTypes[i] = (EntityType) uniqueKeyOwnerReferences.get( name ); 530 } 531 532 if ( ArrayHelper.isAllNegative( owners ) ) owners = null; 533 534 String scalarSelect = renderScalarSelect(); 536 int scalarSize = scalarTypes.size(); 537 hasScalars = scalarTypes.size() != rtsize; 538 539 returnTypes = new Type[scalarSize]; 540 for ( int i = 0; i < scalarSize; i++ ) { 541 returnTypes[i] = ( Type ) scalarTypes.get( i ); 542 } 543 544 QuerySelect sql = new QuerySelect( getFactory().getDialect() ); 545 sql.setDistinct( distinct ); 546 547 if ( !shallowQuery ) { 548 renderIdentifierSelect( sql ); 549 renderPropertiesSelect( sql ); 550 } 551 552 if ( collectionPersister != null ) { 553 sql.addSelectFragmentString( collectionPersister.selectFragment( fetchName, "__" ) ); 554 } 555 556 if ( hasScalars || shallowQuery ) sql.addSelectFragmentString( scalarSelect ); 557 558 mergeJoins( sql.getJoinFragment() ); 560 561 sql.setWhereTokens( whereTokens.iterator() ); 562 563 sql.setGroupByTokens( groupByTokens.iterator() ); 564 sql.setHavingTokens( havingTokens.iterator() ); 565 sql.setOrderByTokens( orderByTokens.iterator() ); 566 567 if ( collectionPersister != null && collectionPersister.hasOrdering() ) { 568 sql.addOrderBy( collectionPersister.getSQLOrderByString( fetchName ) ); 569 } 570 571 scalarColumnNames = NameGenerator.generateColumnNames( returnTypes, getFactory() ); 572 573 Iterator iter = collections.values().iterator(); 575 while ( iter.hasNext() ) { 576 CollectionPersister p = getCollectionPersister( ( String ) iter.next() ); 577 addQuerySpaces( p.getCollectionSpaces() ); 578 } 579 iter = typeMap.keySet().iterator(); 580 while ( iter.hasNext() ) { 581 Queryable p = getEntityPersisterForName( ( String ) iter.next() ); 582 addQuerySpaces( p.getQuerySpaces() ); 583 } 584 585 sqlString = sql.toQueryString(); 586 587 if ( holderClass != null ) holderConstructor = ReflectHelper.getConstructor( holderClass, returnTypes ); 588 589 if ( hasScalars ) { 590 actualReturnTypes = returnTypes; 591 } 592 else { 593 actualReturnTypes = new Type[selectLength]; 594 int j = 0; 595 for ( int i = 0; i < persisters.length; i++ ) { 596 if ( includeInSelect[i] ) { 597 actualReturnTypes[j++] = TypeFactory.manyToOne( persisters[i].getEntityName(), shallowQuery ); 598 } 599 } 600 } 601 602 } 603 604 private void renderIdentifierSelect(QuerySelect sql) { 605 int size = returnedTypes.size(); 606 607 for ( int k = 0; k < size; k++ ) { 608 String name = ( String ) returnedTypes.get( k ); 609 String suffix = size == 1 ? "" : Integer.toString( k ) + '_'; 610 sql.addSelectFragmentString( persisters[k].identifierSelectFragment( name, suffix ) ); 611 } 612 613 } 614 615 630 631 private void renderPropertiesSelect(QuerySelect sql) { 632 int size = returnedTypes.size(); 633 for ( int k = 0; k < size; k++ ) { 634 String suffix = size == 1 ? "" : Integer.toString( k ) + '_'; 635 String name = ( String ) returnedTypes.get( k ); 636 sql.addSelectFragmentString( persisters[k].propertySelectFragment( name, suffix, false ) ); 637 } 638 } 639 640 643 private String renderScalarSelect() { 644 645 boolean isSubselect = superQuery != null; 646 647 StringBuffer buf = new StringBuffer ( 20 ); 648 649 if ( scalarTypes.size() == 0 ) { 650 int size = returnedTypes.size(); 652 for ( int k = 0; k < size; k++ ) { 653 654 scalarTypes.add( TypeFactory.manyToOne( persisters[k].getEntityName(), shallowQuery ) ); 655 656 String [] idColumnNames = persisters[k].getIdentifierColumnNames(); 657 for ( int i = 0; i < idColumnNames.length; i++ ) { 658 buf.append( returnedTypes.get( k ) ).append( '.' ).append( idColumnNames[i] ); 659 if ( !isSubselect ) buf.append( " as " ).append( NameGenerator.scalarName( k, i ) ); 660 if ( i != idColumnNames.length - 1 || k != size - 1 ) buf.append( ", " ); 661 } 662 663 } 664 665 } 666 else { 667 Iterator iter = scalarSelectTokens.iterator(); 669 int c = 0; 670 boolean nolast = false; int parenCount = 0; while ( iter.hasNext() ) { 673 Object next = iter.next(); 674 if ( next instanceof String ) { 675 String token = ( String ) next; 676 677 if ( "(".equals( token ) ) { 678 parenCount++; 679 } 680 else if ( ")".equals( token ) ) { 681 parenCount--; 682 } 683 684 String lc = token.toLowerCase(); 685 if ( lc.equals( ", " ) ) { 686 if ( nolast ) { 687 nolast = false; 688 } 689 else { 690 if ( !isSubselect && parenCount == 0 ) { 691 int x = c++; 692 buf.append( " as " ) 693 .append( NameGenerator.scalarName( x, 0 ) ); 694 } 695 } 696 } 697 buf.append( token ); 698 if ( lc.equals( "distinct" ) || lc.equals( "all" ) ) { 699 buf.append( ' ' ); 700 } 701 } 702 else { 703 nolast = true; 704 String [] tokens = ( String [] ) next; 705 for ( int i = 0; i < tokens.length; i++ ) { 706 buf.append( tokens[i] ); 707 if ( !isSubselect ) { 708 buf.append( " as " ) 709 .append( NameGenerator.scalarName( c, i ) ); 710 } 711 if ( i != tokens.length - 1 ) buf.append( ", " ); 712 } 713 c++; 714 } 715 } 716 if ( !isSubselect && !nolast ) { 717 int x = c++; 718 buf.append( " as " ) 719 .append( NameGenerator.scalarName( x, 0 ) ); 720 } 721 722 } 723 724 return buf.toString(); 725 } 726 727 private void mergeJoins(JoinFragment ojf) throws MappingException, QueryException { 728 729 Iterator iter = joins.entrySet().iterator(); 730 while ( iter.hasNext() ) { 731 Map.Entry me = ( Map.Entry ) iter.next(); 732 String name = ( String ) me.getKey(); 733 JoinSequence join = ( JoinSequence ) me.getValue(); 734 join.setSelector( new JoinSequence.Selector() { 735 public boolean includeSubclasses(String alias) { 736 boolean include = returnedTypes.contains( alias ) && !isShallowQuery(); 737 return include; 738 } 739 } ); 740 741 if ( typeMap.containsKey( name ) ) { 742 ojf.addFragment( join.toJoinFragment( enabledFilters, true ) ); 743 } 744 else if ( collections.containsKey( name ) ) { 745 ojf.addFragment( join.toJoinFragment( enabledFilters, true ) ); 746 } 747 else { 748 } 750 751 } 752 753 } 754 755 public final Set getQuerySpaces() { 756 return querySpaces; 757 } 758 759 764 boolean isShallowQuery() { 765 return shallowQuery; 766 } 767 768 void addQuerySpaces(Serializable [] spaces) { 769 for ( int i = 0; i < spaces.length; i++ ) { 770 querySpaces.add( spaces[i] ); 771 } 772 if ( superQuery != null ) superQuery.addQuerySpaces( spaces ); 773 } 774 775 void setDistinct(boolean distinct) { 776 this.distinct = distinct; 777 } 778 779 boolean isSubquery() { 780 return superQuery != null; 781 } 782 783 786 public CollectionPersister[] getCollectionPersisters() { 787 return collectionPersister == null ? null : new CollectionPersister[] { collectionPersister }; 788 } 789 790 protected String [] getCollectionSuffixes() { 791 return collectionPersister == null ? null : new String [] { "__" }; 792 } 793 794 void setCollectionToFetch(String role, String name, String ownerName, String entityName) 795 throws QueryException { 796 fetchName = name; 797 collectionPersister = getCollectionPersister( role ); 798 collectionOwnerName = ownerName; 799 if ( collectionPersister.getElementType().isEntityType() ) { 800 addEntityToFetch( entityName ); 801 } 802 } 803 804 protected String [] getSuffixes() { 805 return suffixes; 806 } 807 808 protected String [] getAliases() { 809 return names; 810 } 811 812 815 private void addFromAssociation(final String elementName, final String collectionRole) 816 throws QueryException { 817 QueryableCollection persister = getCollectionPersister( collectionRole ); 819 Type collectionElementType = persister.getElementType(); 820 if ( !collectionElementType.isEntityType() ) { 821 throw new QueryException( "collection of values in filter: " + elementName ); 822 } 823 824 String [] keyColumnNames = persister.getKeyColumnNames(); 825 827 String collectionName; 828 JoinSequence join = new JoinSequence( getFactory() ); 829 collectionName = persister.isOneToMany() ? 830 elementName : 831 createNameForCollection( collectionRole ); 832 join.setRoot( persister, collectionName ); 833 if ( !persister.isOneToMany() ) { 834 addCollection( collectionName, collectionRole ); 836 try { 837 join.addJoin( ( AssociationType ) persister.getElementType(), 838 elementName, 839 JoinFragment.INNER_JOIN, 840 persister.getElementColumnNames(collectionName) ); 841 } 842 catch ( MappingException me ) { 843 throw new QueryException( me ); 844 } 845 } 846 join.addCondition( collectionName, keyColumnNames, " = ?" ); 847 EntityType elemType = ( EntityType ) collectionElementType; 849 addFrom( elementName, elemType.getAssociatedEntityName(), join ); 850 851 } 852 853 String getPathAlias(String path) { 854 return ( String ) pathAliases.get( path ); 855 } 856 857 JoinSequence getPathJoin(String path) { 858 return ( JoinSequence ) pathJoins.get( path ); 859 } 860 861 void addPathAliasAndJoin(String path, String alias, JoinSequence joinSequence) { 862 pathAliases.put( path, alias ); 863 pathJoins.put( path, joinSequence ); 864 } 865 866 protected int bindNamedParameters(PreparedStatement ps, Map namedParams, int start, SessionImplementor session) 867 throws SQLException , HibernateException { 868 if ( namedParams != null ) { 869 Iterator iter = namedParams.entrySet().iterator(); 871 int result = 0; 872 while ( iter.hasNext() ) { 873 Map.Entry e = ( Map.Entry ) iter.next(); 874 String name = ( String ) e.getKey(); 875 TypedValue typedval = ( TypedValue ) e.getValue(); 876 int[] locs = getNamedParameterLocs( name ); 877 for ( int i = 0; i < locs.length; i++ ) { 878 typedval.getType().nullSafeSet( ps, typedval.getValue(), locs[i] + start, session ); 879 } 880 result += locs.length; 881 } 882 return result; 883 } 884 else { 885 return 0; 886 } 887 } 888 889 public List list(SessionImplementor session, QueryParameters queryParameters) 890 throws HibernateException { 891 return list( session, queryParameters, getQuerySpaces(), actualReturnTypes ); 892 } 893 894 897 public Iterator iterate(QueryParameters queryParameters, EventSource session) 898 throws HibernateException { 899 900 boolean stats = session.getFactory().getStatistics().isStatisticsEnabled(); 901 long startTime = 0; 902 if ( stats ) startTime = System.currentTimeMillis(); 903 904 try { 905 906 PreparedStatement st = prepareQueryStatement( queryParameters, false, session ); 907 ResultSet rs = getResultSet( st, false, queryParameters.getRowSelection(), session ); 908 HolderInstantiator hi = new HolderInstantiator(holderConstructor, false, false, null); 909 Iterator result = new IteratorImpl( rs, st, session, returnTypes, getColumnNames(), hi ); 910 911 if ( stats ) { 912 session.getFactory().getStatisticsImplementor().queryExecuted( 913 "HQL: " + queryString, 914 0, 915 System.currentTimeMillis() - startTime ); 916 } 917 918 return result; 919 920 } 921 catch ( SQLException sqle ) { 922 throw JDBCExceptionHelper.convert( 923 getFactory().getSQLExceptionConverter(), 924 sqle, 925 "could not execute query using iterate", 926 getSQLString() 927 ); 928 } 929 930 } 931 932 public int executeUpdate(QueryParameters queryParameters, SessionImplementor session) throws HibernateException { 933 throw new UnsupportedOperationException ( "Not supported! Use the AST translator..."); 934 } 935 936 protected Object getResultColumnOrRow(Object [] row, ResultSet rs, SessionImplementor session) 937 throws SQLException , HibernateException { 938 row = toResultRow( row ); 939 if ( hasScalars ) { 940 String [][] scalarColumns = getColumnNames(); 941 int queryCols = returnTypes.length; 942 if ( holderClass == null && queryCols == 1 ) { 943 return returnTypes[0].nullSafeGet( rs, scalarColumns[0], session, null ); 944 } 945 else { 946 row = new Object [queryCols]; 947 for ( int i = 0; i < queryCols; i++ ) 948 row[i] = returnTypes[i].nullSafeGet( rs, scalarColumns[i], session, null ); 949 return row; 950 } 951 } 952 else if ( holderClass == null ) { 953 return row.length == 1 ? row[0] : row; 954 } 955 else { 956 return row; 957 } 958 959 } 960 961 protected List getResultList(List results) throws QueryException { 962 if ( holderClass != null ) { 963 for ( int i = 0; i < results.size(); i++ ) { 964 Object [] row = ( Object [] ) results.get( i ); 965 try { 966 results.set( i, holderConstructor.newInstance( row ) ); 967 } 968 catch ( Exception e ) { 969 throw new QueryException( "could not instantiate: " + holderClass, e ); 970 } 971 } 972 } 973 return results; 974 } 975 976 private Object [] toResultRow(Object [] row) { 977 if ( selectLength == row.length ) { 978 return row; 979 } 980 else { 981 Object [] result = new Object [selectLength]; 982 int j = 0; 983 for ( int i = 0; i < row.length; i++ ) { 984 if ( includeInSelect[i] ) result[j++] = row[i]; 985 } 986 return result; 987 } 988 } 989 990 void setHolderClass(Class clazz) { 991 holderClass = clazz; 992 } 993 994 protected LockMode[] getLockModes(Map lockModes) { 995 HashMap nameLockModes = new HashMap (); 999 if ( lockModes != null ) { 1000 Iterator iter = lockModes.entrySet().iterator(); 1001 while ( iter.hasNext() ) { 1002 Map.Entry me = ( Map.Entry ) iter.next(); 1003 nameLockModes.put( getAliasName( ( String ) me.getKey() ), 1004 me.getValue() ); 1005 } 1006 } 1007 LockMode[] lockModeArray = new LockMode[names.length]; 1008 for ( int i = 0; i < names.length; i++ ) { 1009 LockMode lm = ( LockMode ) nameLockModes.get( names[i] ); 1010 if ( lm == null ) lm = LockMode.NONE; 1011 lockModeArray[i] = lm; 1012 } 1013 return lockModeArray; 1014 } 1015 1016 protected String applyLocks(String sql, Map lockModes, Dialect dialect) throws QueryException { 1017 final String result; 1019 if ( lockModes == null || lockModes.size() == 0 ) { 1020 result = sql; 1021 } 1022 else { 1023 Map aliasedLockModes = new HashMap (); 1024 Iterator iter = lockModes.entrySet().iterator(); 1025 while ( iter.hasNext() ) { 1026 Map.Entry me = ( Map.Entry ) iter.next(); 1027 aliasedLockModes.put( getAliasName( ( String ) me.getKey() ), me.getValue() ); 1028 } 1029 Map keyColumnNames = null; 1030 if ( dialect.forUpdateOfColumns() ) { 1031 keyColumnNames = new HashMap (); 1032 for ( int i = 0; i < names.length; i++ ) { 1033 keyColumnNames.put( names[i], persisters[i].getIdentifierColumnNames() ); 1034 } 1035 } 1036 result = sql + new ForUpdateFragment( dialect, aliasedLockModes, keyColumnNames ).toFragmentString(); 1037 } 1038 logQuery( queryString, result ); 1039 return result; 1040 } 1041 1042 protected boolean upgradeLocks() { 1043 return true; 1044 } 1045 1046 protected int[] getCollectionOwners() { 1047 return new int[] { collectionOwnerColumn }; 1048 } 1049 1050 protected boolean isCompiled() { 1051 return compiled; 1052 } 1053 1054 public String toString() { 1055 return queryString; 1056 } 1057 1058 protected int[] getOwners() { 1059 return owners; 1060 } 1061 1062 protected EntityType[] getOwnerAssociationTypes() { 1063 return ownerAssociationTypes; 1064 } 1065 1066 public Class getHolderClass() { 1067 return holderClass; 1068 } 1069 1070 public Map getEnabledFilters() { 1071 return enabledFilters; 1072 } 1073 1074 public ScrollableResults scroll(final QueryParameters queryParameters, 1075 final SessionImplementor session) 1076 throws HibernateException { 1077 HolderInstantiator hi = new HolderInstantiator(holderConstructor, false, false, null); 1078 return scroll( queryParameters, returnTypes, hi, session ); 1079 } 1080 1081 protected String getQueryIdentifier() { 1082 return queryString; 1083 } 1084 1085 protected boolean isSubselectLoadingEnabled() { 1086 return hasSubselectLoadableCollections(); 1087 } 1088 1089 public void validateScrollability() throws HibernateException { 1090 if ( getCollectionPersisters() != null ) { 1092 throw new HibernateException( "Cannot scroll queries which initialize collections" ); 1093 } 1094 } 1095 1096 public boolean containsCollectionFetches() { 1097 return false; 1098 } 1099} 1100 | Popular Tags |