1 package org.hibernate.loader; 3 4 import java.io.Serializable ; 5 import java.sql.CallableStatement ; 6 import java.sql.PreparedStatement ; 7 import java.sql.ResultSet ; 8 import java.sql.SQLException ; 9 import java.util.ArrayList ; 10 import java.util.Arrays ; 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.logging.Log; 18 import org.apache.commons.logging.LogFactory; 19 import org.hibernate.AssertionFailure; 20 import org.hibernate.HibernateException; 21 import org.hibernate.LockMode; 22 import org.hibernate.QueryException; 23 import org.hibernate.ScrollMode; 24 import org.hibernate.ScrollableResults; 25 import org.hibernate.StaleObjectStateException; 26 import org.hibernate.WrongClassException; 27 import org.hibernate.cache.FilterKey; 28 import org.hibernate.cache.QueryCache; 29 import org.hibernate.cache.QueryKey; 30 import org.hibernate.collection.PersistentCollection; 31 import org.hibernate.dialect.Dialect; 32 import org.hibernate.engine.EntityKey; 33 import org.hibernate.engine.EntityUniqueKey; 34 import org.hibernate.engine.PersistenceContext; 35 import org.hibernate.engine.QueryParameters; 36 import org.hibernate.engine.RowSelection; 37 import org.hibernate.engine.SessionFactoryImplementor; 38 import org.hibernate.engine.SessionImplementor; 39 import org.hibernate.engine.SubselectFetch; 40 import org.hibernate.engine.TwoPhaseLoad; 41 import org.hibernate.event.EventSource; 42 import org.hibernate.event.PostLoadEvent; 43 import org.hibernate.event.PreLoadEvent; 44 import org.hibernate.exception.JDBCExceptionHelper; 45 import org.hibernate.hql.HolderInstantiator; 46 import org.hibernate.impl.ScrollableResultsImpl; 47 import org.hibernate.impl.FetchingScrollableResultsImpl; 48 import org.hibernate.jdbc.ColumnNameCache; 49 import org.hibernate.jdbc.ResultSetWrapper; 50 import org.hibernate.persister.collection.CollectionPersister; 51 import org.hibernate.persister.entity.EntityPersister; 52 import org.hibernate.persister.entity.Loadable; 53 import org.hibernate.persister.entity.UniqueKeyLoadable; 54 import org.hibernate.pretty.MessageHelper; 55 import org.hibernate.proxy.HibernateProxy; 56 import org.hibernate.type.AssociationType; 57 import org.hibernate.type.EntityType; 58 import org.hibernate.type.Type; 59 import org.hibernate.type.VersionType; 60 import org.hibernate.util.StringHelper; 61 62 76 public abstract class Loader { 77 78 private static final Log log = LogFactory.getLog( Loader.class ); 79 80 private final SessionFactoryImplementor factory; 81 private ColumnNameCache columnNameCache; 82 83 public Loader(SessionFactoryImplementor factory) { 84 this.factory = factory; 85 } 86 87 90 protected abstract String getSQLString(); 91 92 96 protected abstract Loadable[] getEntityPersisters(); 97 98 102 protected boolean[] getEntityEagerPropertyFetches() { 103 return null; 104 } 105 106 110 protected int[] getOwners() { 111 return null; 112 } 113 114 118 protected EntityType[] getOwnerAssociationTypes() { 119 return null; 120 } 121 122 126 protected CollectionPersister[] getCollectionPersisters() { 127 return null; 128 } 129 130 135 protected int[] getCollectionOwners() { 136 return null; 137 } 138 139 144 protected abstract LockMode[] getLockModes(Map lockModes); 145 146 151 protected String applyLocks(String sql, Map lockModes, Dialect dialect) throws HibernateException { 152 return sql; 153 } 154 155 159 protected boolean upgradeLocks() { 160 return false; 161 } 162 163 166 protected boolean isSingleRowLoader() { 167 return false; 168 } 169 170 176 protected String [] getAliases() { 177 return null; 178 } 179 180 183 protected String preprocessSQL(String sql, QueryParameters parameters, Dialect dialect) 184 throws HibernateException { 185 186 sql = applyLocks( sql, parameters.getLockModes(), dialect ); 187 188 return getFactory().getSettings().isCommentsEnabled() ? 189 prependComment( sql, parameters ) : sql; 190 } 191 192 private String prependComment(String sql, QueryParameters parameters) { 193 String comment = parameters.getComment(); 194 if ( comment == null ) { 195 return sql; 196 } 197 else { 198 return new StringBuffer ( comment.length() + sql.length() + 5 ) 199 .append( "/* " ) 200 .append( comment ) 201 .append( " */ " ) 202 .append( sql ) 203 .toString(); 204 } 205 } 206 207 212 private List doQueryAndInitializeNonLazyCollections(final SessionImplementor session, 213 final QueryParameters queryParameters, 214 final boolean returnProxies) 215 throws HibernateException, SQLException { 216 217 final PersistenceContext persistenceContext = session.getPersistenceContext(); 218 persistenceContext.beforeLoad(); 219 List result; 220 try { 221 result = doQuery( session, queryParameters, returnProxies ); 222 } 223 finally { 224 persistenceContext.afterLoad(); 225 } 226 persistenceContext.initializeNonLazyCollections(); 227 return result; 228 } 229 230 241 public Object loadSingleRow( 242 final ResultSet resultSet, 243 final SessionImplementor session, 244 final QueryParameters queryParameters, 245 final boolean returnProxies) throws HibernateException { 246 247 final int entitySpan = getEntityPersisters().length; 248 final List hydratedObjects = entitySpan == 0 ? null : new ArrayList ( entitySpan ); 249 250 final Object result; 251 try { 252 result = getRowFromResultSet( 253 resultSet, 254 session, 255 queryParameters, 256 getLockModes( queryParameters.getLockModes() ), 257 null, 258 hydratedObjects, 259 new EntityKey[entitySpan], 260 returnProxies 261 ); 262 } 263 catch ( SQLException sqle ) { 264 throw JDBCExceptionHelper.convert( 265 factory.getSQLExceptionConverter(), 266 sqle, 267 "could not read next row of results", 268 getSQLString() 269 ); 270 } 271 272 initializeEntitiesAndCollections( hydratedObjects, resultSet, session, queryParameters.isReadOnly() ); 273 session.getPersistenceContext().initializeNonLazyCollections(); 274 return result; 275 } 276 277 private Object sequentialLoad( 278 final ResultSet resultSet, 279 final SessionImplementor session, 280 final QueryParameters queryParameters, 281 final boolean returnProxies, 282 final EntityKey keyToRead) throws HibernateException { 283 284 final int entitySpan = getEntityPersisters().length; 285 final List hydratedObjects = entitySpan == 0 ? null : new ArrayList ( entitySpan ); 286 287 Object result = null; 288 final EntityKey[] loadedKeys = new EntityKey[entitySpan]; 289 290 try { 291 do { 292 Object loaded = getRowFromResultSet( 293 resultSet, 294 session, 295 queryParameters, 296 getLockModes( queryParameters.getLockModes() ), 297 null, 298 hydratedObjects, 299 loadedKeys, 300 returnProxies 301 ); 302 if ( result == null ) { 303 result = loaded; 304 } 305 } while ( keyToRead.equals( loadedKeys[0] ) && resultSet.next() ); 306 } 307 catch ( SQLException sqle ) { 308 throw JDBCExceptionHelper.convert( 309 factory.getSQLExceptionConverter(), 310 sqle, 311 "could not perform sequential read of results (forward)", 312 getSQLString() 313 ); 314 } 315 316 initializeEntitiesAndCollections( hydratedObjects, resultSet, session, queryParameters.isReadOnly() ); 317 session.getPersistenceContext().initializeNonLazyCollections(); 318 return result; 319 } 320 321 334 public Object loadSequentialRowsForward( 335 final ResultSet resultSet, 336 final SessionImplementor session, 337 final QueryParameters queryParameters, 338 final boolean returnProxies) throws HibernateException { 339 340 343 try { 344 if ( resultSet.isAfterLast() ) { 345 return null; 347 } 348 349 if ( resultSet.isBeforeFirst() ) { 350 resultSet.first(); 351 } 352 353 final EntityKey currentKey = getKeyFromResultSet( 360 0, 361 getEntityPersisters()[0], 362 null, 363 resultSet, 364 session 365 ); 366 367 return sequentialLoad( resultSet, session, queryParameters, returnProxies, currentKey ); 368 } 369 catch ( SQLException sqle ) { 370 throw JDBCExceptionHelper.convert( 371 factory.getSQLExceptionConverter(), 372 sqle, 373 "could not perform sequential read of results (forward)", 374 getSQLString() 375 ); 376 } 377 } 378 379 392 public Object loadSequentialRowsReverse( 393 final ResultSet resultSet, 394 final SessionImplementor session, 395 final QueryParameters queryParameters, 396 final boolean returnProxies, 397 final boolean isLogicallyAfterLast) throws HibernateException { 398 399 402 try { 403 if ( resultSet.isFirst() ) { 404 return null; 406 } 407 408 EntityKey keyToRead = null; 409 if ( resultSet.isAfterLast() && isLogicallyAfterLast ) { 422 resultSet.last(); 424 keyToRead = getKeyFromResultSet( 425 0, 426 getEntityPersisters()[0], 427 null, 428 resultSet, 429 session 430 ); 431 } 432 else { 433 resultSet.previous(); 438 439 boolean firstPass = true; 444 final EntityKey lastKey = getKeyFromResultSet( 445 0, 446 getEntityPersisters()[0], 447 null, 448 resultSet, 449 session 450 ); 451 while ( resultSet.previous() ) { 452 EntityKey checkKey = getKeyFromResultSet( 453 0, 454 getEntityPersisters()[0], 455 null, 456 resultSet, 457 session 458 ); 459 460 if ( firstPass ) { 461 firstPass = false; 462 keyToRead = checkKey; 463 } 464 465 if ( !lastKey.equals( checkKey ) ) { 466 break; 467 } 468 } 469 470 } 471 472 while ( resultSet.previous() ) { 475 EntityKey checkKey = getKeyFromResultSet( 476 0, 477 getEntityPersisters()[0], 478 null, 479 resultSet, 480 session 481 ); 482 483 if ( !keyToRead.equals( checkKey ) ) { 484 break; 485 } 486 } 487 488 resultSet.next(); 491 492 return sequentialLoad( resultSet, session, queryParameters, returnProxies, keyToRead ); 494 } 495 catch ( SQLException sqle ) { 496 throw JDBCExceptionHelper.convert( 497 factory.getSQLExceptionConverter(), 498 sqle, 499 "could not perform sequential read of results (forward)", 500 getSQLString() 501 ); 502 } 503 } 504 505 private static EntityKey getOptionalObjectKey(QueryParameters queryParameters, SessionImplementor session) { 506 final Object optionalObject = queryParameters.getOptionalObject(); 507 final Serializable optionalId = queryParameters.getOptionalId(); 508 final String optionalEntityName = queryParameters.getOptionalEntityName(); 509 510 if ( optionalObject != null && optionalEntityName != null ) { 511 return new EntityKey( optionalId, 512 session.getEntityPersister( optionalEntityName, optionalObject ), 513 session.getEntityMode() 514 ); 515 } 516 else { 517 return null; 518 } 519 520 } 521 522 private Object getRowFromResultSet( 523 final ResultSet resultSet, 524 final SessionImplementor session, 525 final QueryParameters queryParameters, 526 final LockMode[] lockModeArray, 527 final EntityKey optionalObjectKey, 528 final List hydratedObjects, 529 final EntityKey[] keys, 530 boolean returnProxies) 531 throws SQLException , HibernateException { 532 533 final Loadable[] persisters = getEntityPersisters(); 534 final int entitySpan = persisters.length; 535 536 for ( int i = 0; i < entitySpan; i++ ) { 537 keys[i] = getKeyFromResultSet( 538 i, 539 persisters[i], 540 i == entitySpan - 1 ? 541 queryParameters.getOptionalId() : 542 null, 543 resultSet, 544 session 545 ); 546 } 548 549 registerNonExists( keys, persisters, session ); 550 551 Object [] row = getRow( 553 resultSet, 554 persisters, 555 keys, 556 queryParameters.getOptionalObject(), 557 optionalObjectKey, 558 lockModeArray, 559 hydratedObjects, 560 session 561 ); 562 563 readCollectionElements( row, resultSet, session ); 564 565 if ( returnProxies ) { 566 for ( int i = 0; i < entitySpan; i++ ) { 568 Object entity = row[i]; 569 Object proxy = session.getPersistenceContext().proxyFor( persisters[i], keys[i], entity ); 570 if ( entity != proxy ) { 571 ( (HibernateProxy) proxy ).getHibernateLazyInitializer().setImplementation(entity); 573 row[i] = proxy; 574 } 575 } 576 } 577 578 return getResultColumnOrRow( row, resultSet, session ); 579 580 } 581 582 585 private void readCollectionElements(Object [] row, ResultSet resultSet, SessionImplementor session) 586 throws SQLException , HibernateException { 587 588 590 final CollectionPersister[] collectionPersisters = getCollectionPersisters(); 591 if ( collectionPersisters != null ) { 592 593 final CollectionAliases[] descriptors = getCollectionAliases(); 594 final int[] collectionOwners = getCollectionOwners(); 595 596 for ( int i=0; i<collectionPersisters.length; i++ ) { 597 598 final boolean hasCollectionOwners = collectionOwners !=null && 599 collectionOwners[i] > -1; 600 603 final Object owner = hasCollectionOwners ? 604 row[ collectionOwners[i] ] : 605 null; 607 final CollectionPersister collectionPersister = collectionPersisters[i]; 608 final Serializable key; 609 if ( owner == null ) { 610 key = null; 611 } 612 else { 613 key = collectionPersister.getCollectionType() 614 .getKeyOfOwner( owner, session ); 615 } 618 619 readCollectionElement( owner, key, collectionPersister, descriptors[i], resultSet, session ); 620 621 } 622 623 } 624 } 625 626 private List doQuery(final SessionImplementor session, 627 final QueryParameters queryParameters, 628 final boolean returnProxies) throws SQLException , HibernateException { 629 630 final RowSelection selection = queryParameters.getRowSelection(); 631 final int maxRows = hasMaxRows( selection ) ? 632 selection.getMaxRows().intValue() : 633 Integer.MAX_VALUE; 634 635 final int entitySpan = getEntityPersisters().length; 636 637 final ArrayList hydratedObjects = entitySpan == 0 ? null : new ArrayList ( entitySpan * 10 ); 638 final PreparedStatement st = prepareQueryStatement( queryParameters, false, session ); 639 final ResultSet rs = getResultSet( st, queryParameters.isCallable(), selection, session ); 640 641 final LockMode[] lockModeArray = getLockModes( queryParameters.getLockModes() ); 647 final EntityKey optionalObjectKey = getOptionalObjectKey( queryParameters, session ); 648 649 final boolean createSubselects = isSubselectLoadingEnabled(); 650 final List subselectResultKeys = createSubselects ? new ArrayList () : null; 651 final List results = new ArrayList (); 652 653 try { 654 655 handleEmptyCollections( queryParameters.getCollectionKeys(), rs, session ); 656 657 EntityKey[] keys = new EntityKey[entitySpan]; 659 if ( log.isTraceEnabled() ) log.trace( "processing result set" ); 660 661 int count; 662 for ( count = 0; count < maxRows && rs.next(); count++ ) { 663 664 if ( log.isTraceEnabled() ) log.debug("result set row: " + count); 665 666 Object result = getRowFromResultSet( rs, 667 session, 668 queryParameters, 669 lockModeArray, 670 optionalObjectKey, 671 hydratedObjects, 672 keys, 673 returnProxies ); 674 results.add( result ); 675 676 if ( createSubselects ) { 677 subselectResultKeys.add(keys); 678 keys = new EntityKey[entitySpan]; } 680 681 } 682 683 if ( log.isTraceEnabled() ) log.trace( "done processing result set (" + count + " rows)" ); 684 685 } 686 finally { 687 session.getBatcher().closeQueryStatement( st, rs ); 688 } 689 690 initializeEntitiesAndCollections( hydratedObjects, rs, session, queryParameters.isReadOnly() ); 691 692 if ( createSubselects ) createSubselects( subselectResultKeys, queryParameters, session ); 693 694 return results; 696 } 697 698 protected boolean isSubselectLoadingEnabled() { 699 return false; 700 } 701 702 protected boolean hasSubselectLoadableCollections() { 703 final Loadable[] loadables = getEntityPersisters(); 704 for (int i=0; i<loadables.length; i++ ) { 705 if ( loadables[i].hasSubselectLoadableCollections() ) return true; 706 } 707 return false; 708 } 709 710 private static Set [] transpose( List keys ) { 711 Set [] result = new Set [ ( ( EntityKey[] ) keys.get(0) ).length ]; 712 for ( int j=0; j<result.length; j++ ) { 713 result[j] = new HashSet ( keys.size() ); 714 for ( int i=0; i<keys.size(); i++ ) { 715 result[j].add( ( ( EntityKey[] ) keys.get(i) ) [j] ); 716 } 717 } 718 return result; 719 } 720 721 private void createSubselects(List keys, QueryParameters queryParameters, SessionImplementor session) { 722 if ( keys.size() > 1 ) { 724 Set [] keySets = transpose(keys); 725 726 final Loadable[] loadables = getEntityPersisters(); 727 final String [] aliases = getAliases(); 728 final Iterator iter = keys.iterator(); 729 while ( iter.hasNext() ) { 730 731 final EntityKey[] rowKeys = (EntityKey[]) iter.next(); 732 for ( int i=0; i<rowKeys.length; i++ ) { 733 734 if ( rowKeys[i]!=null && loadables[i].hasSubselectLoadableCollections() ) { 735 736 SubselectFetch subselectFetch = new SubselectFetch( 737 aliases[i], 739 loadables[i], 740 queryParameters, 741 keySets[i] 742 ); 743 744 session.getPersistenceContext() 745 .getBatchFetchQueue() 746 .addSubselect( rowKeys[i], subselectFetch ); 747 } 748 749 } 750 751 } 752 } 753 } 754 755 private void initializeEntitiesAndCollections( 756 final List hydratedObjects, 757 final Object resultSetId, 758 final SessionImplementor session, 759 final boolean readOnly) 760 throws HibernateException { 761 762 final CollectionPersister[] collectionPersisters = getCollectionPersisters(); 763 if ( collectionPersisters != null ) { 764 for ( int i=0; i<collectionPersisters.length; i++ ) { 765 if ( collectionPersisters[i].isArray() ) { 766 endCollectionLoad( resultSetId, session, collectionPersisters[i] ); 772 } 773 } 774 } 775 776 final PreLoadEvent pre; 778 final PostLoadEvent post; 779 if ( session.isEventSource() ) { 780 pre = new PreLoadEvent( (EventSource) session ); 781 post = new PostLoadEvent( (EventSource) session ); 782 } 783 else { 784 pre = null; 785 post = null; 786 } 787 788 if ( hydratedObjects!=null ) { 789 int hydratedObjectsSize = hydratedObjects.size(); 790 if ( log.isTraceEnabled() ) log.trace( "total objects hydrated: " + hydratedObjectsSize ); 791 for ( int i = 0; i < hydratedObjectsSize; i++ ) { 792 TwoPhaseLoad.initializeEntity( hydratedObjects.get(i), readOnly, session, pre, post ); 793 } 794 } 795 796 if ( collectionPersisters != null ) { 797 for ( int i=0; i<collectionPersisters.length; i++ ) { 798 if ( !collectionPersisters[i].isArray() ) { 799 endCollectionLoad( resultSetId, session, collectionPersisters[i] ); 804 } 805 } 806 } 807 808 } 809 810 private void endCollectionLoad( 811 final Object resultSetId, 812 final SessionImplementor session, 813 final CollectionPersister collectionPersister 814 ) { 815 session.getPersistenceContext().getCollectionLoadContext() 817 .endLoadingCollections( collectionPersister, resultSetId, session ); 818 } 819 820 protected List getResultList(List results) throws QueryException { 821 return results; 822 } 823 824 829 protected Object getResultColumnOrRow(Object [] row, ResultSet rs, SessionImplementor session) 830 throws SQLException , HibernateException { 831 return row; 832 } 833 834 839 private void registerNonExists( 840 final EntityKey[] keys, 841 final Loadable[] persisters, 842 final SessionImplementor session) { 843 844 final int[] owners = getOwners(); 845 if ( owners != null ) { 846 847 EntityType[] ownerAssociationTypes = getOwnerAssociationTypes(); 848 for ( int i = 0; i < keys.length; i++ ) { 849 850 int owner = owners[i]; 851 if ( owner > -1 ) { 852 EntityKey ownerKey = keys[owner]; 853 if ( keys[i] == null && ownerKey != null ) { 854 855 final PersistenceContext persistenceContext = session.getPersistenceContext(); 856 857 867 868 875 boolean isOneToOneAssociation = ownerAssociationTypes!=null && 876 ownerAssociationTypes[i]!=null && 877 ownerAssociationTypes[i].isOneToOne(); 878 if ( isOneToOneAssociation ) { 879 persistenceContext.addNullProperty( ownerKey, 880 ownerAssociationTypes[i].getPropertyName() ); 881 } 882 892 } 893 } 894 } 895 } 896 } 897 898 901 private void readCollectionElement( 902 final Object optionalOwner, 903 final Serializable optionalKey, 904 final CollectionPersister persister, 905 final CollectionAliases descriptor, 906 final ResultSet rs, 907 final SessionImplementor session) 908 throws HibernateException, SQLException { 909 910 final PersistenceContext persistenceContext = session.getPersistenceContext(); 911 912 final Serializable collectionRowKey = (Serializable ) persister.readKey( 913 rs, 914 descriptor.getSuffixedKeyAliases(), 915 session 916 ); 917 918 if ( collectionRowKey != null ) { 919 921 if ( log.isDebugEnabled() ) { 922 log.debug( "found row of collection: " + 923 MessageHelper.collectionInfoString( persister, collectionRowKey, getFactory() ) ); 924 } 925 926 Object owner = optionalOwner; 927 if ( owner == null ) { 928 owner = persistenceContext.getCollectionOwner( collectionRowKey, persister ); 929 if ( owner == null ) { 930 } 936 } 937 938 PersistentCollection rowCollection = persistenceContext.getCollectionLoadContext() 939 .getLoadingCollection( persister, collectionRowKey, rs, session.getEntityMode() ); 940 941 if ( rowCollection != null ) { 942 rowCollection.readFrom( rs, persister, descriptor, owner ); 943 } 944 945 } 946 else if ( optionalKey != null ) { 947 951 if ( log.isDebugEnabled() ) { 952 log.debug( "result set contains (possibly empty) collection: " + 953 MessageHelper.collectionInfoString( persister, optionalKey, getFactory() ) ); 954 } 955 956 persistenceContext.getCollectionLoadContext() 957 .getLoadingCollection( persister, optionalKey, rs, session.getEntityMode() ); 959 } 960 961 963 } 964 965 970 private void handleEmptyCollections( 971 final Serializable [] keys, 972 final Object resultSetId, 973 final SessionImplementor session) throws HibernateException { 974 975 if ( keys != null ) { 976 980 CollectionPersister[] collectionPersisters = getCollectionPersisters(); 981 for ( int j=0; j<collectionPersisters.length; j++ ) { 982 for ( int i = 0; i < keys.length; i++ ) { 983 985 if ( log.isDebugEnabled() ) { 986 log.debug( 987 "result set contains (possibly empty) collection: " + 988 MessageHelper.collectionInfoString( collectionPersisters[j], keys[i], getFactory() ) 989 ); 990 } 991 992 session.getPersistenceContext() 993 .getCollectionLoadContext() 994 .getLoadingCollection( 995 collectionPersisters[j], 996 keys[i], 997 resultSetId, 998 session.getEntityMode() 999 ); 1000 } 1001 } 1002 1003 } 1004 1005 } 1008 1009 1015 private EntityKey getKeyFromResultSet( 1016 final int i, 1017 final Loadable persister, 1018 final Serializable id, 1019 final ResultSet rs, 1020 final SessionImplementor session) throws HibernateException, SQLException { 1021 1022 Serializable resultId; 1023 1024 1028 if ( isSingleRowLoader() && id != null ) { 1029 resultId = id; 1030 } 1031 else { 1032 1033 Type idType = persister.getIdentifierType(); 1034 resultId = (Serializable ) idType.nullSafeGet( 1035 rs, 1036 getEntityAliases()[i].getSuffixedKeyAliases(), 1037 session, 1038 null ); 1040 1041 final boolean idIsResultId = id != null && 1042 resultId != null && 1043 idType.isEqual( id, resultId, session.getEntityMode(), factory ); 1044 1045 if ( idIsResultId ) resultId = id; } 1047 1048 return resultId == null ? 1049 null : 1050 new EntityKey( resultId, persister, session.getEntityMode() ); 1051 } 1052 1053 1058 private void checkVersion( 1059 final int i, 1060 final Loadable persister, 1061 final Serializable id, 1062 final Object entity, 1063 final ResultSet rs, 1064 final SessionImplementor session) 1065 throws HibernateException, SQLException { 1066 1067 Object version = session.getPersistenceContext().getEntry( entity ).getVersion(); 1068 1069 if ( version != null ) { VersionType versionType = persister.getVersionType(); 1071 Object currentVersion = versionType.nullSafeGet( 1072 rs, 1073 getEntityAliases()[i].getSuffixedVersionAliases(), 1074 session, 1075 null 1076 ); 1077 if ( !versionType.isEqual(version, currentVersion) ) { 1078 throw new StaleObjectStateException( persister.getEntityName(), id ); 1079 } 1080 } 1081 1082 } 1083 1084 1091 private Object [] getRow( 1092 final ResultSet rs, 1093 final Loadable[] persisters, 1094 final EntityKey[] keys, 1095 final Object optionalObject, 1096 final EntityKey optionalObjectKey, 1097 final LockMode[] lockModes, 1098 final List hydratedObjects, 1099 final SessionImplementor session) 1100 throws HibernateException, SQLException { 1101 1102 final int cols = persisters.length; 1103 final EntityAliases[] descriptors = getEntityAliases(); 1104 1105 if ( log.isDebugEnabled() ) { 1106 log.debug( 1107 "result row: " + 1108 StringHelper.toString( keys ) 1109 ); 1110 } 1111 1112 final Object [] rowResults = new Object [cols]; 1113 1114 for ( int i = 0; i < cols; i++ ) { 1115 1116 Object object = null; 1117 EntityKey key = keys[i]; 1118 1119 if ( keys[i] == null ) { 1120 } 1122 else { 1123 1124 object = session.getEntityUsingInterceptor( key ); 1126 if ( object != null ) { 1127 instanceAlreadyLoaded( 1129 rs, 1130 i, 1131 persisters[i], 1132 key, 1133 object, 1134 lockModes[i], 1135 session 1136 ); 1137 } 1138 else { 1139 object = instanceNotYetLoaded( 1140 rs, 1141 i, 1142 persisters[i], 1143 descriptors[i].getRowIdAlias(), 1144 key, 1145 lockModes[i], 1146 optionalObjectKey, 1147 optionalObject, 1148 hydratedObjects, 1149 session 1150 ); 1151 } 1152 1153 } 1154 1155 rowResults[i] = object; 1156 1157 } 1158 1159 return rowResults; 1160 1161 } 1162 1163 1166 private void instanceAlreadyLoaded( 1167 final ResultSet rs, 1168 final int i, 1169 final Loadable persister, 1170 final EntityKey key, 1171 final Object object, 1172 final LockMode lockMode, 1173 final SessionImplementor session) 1174 throws HibernateException, SQLException { 1175 1176 if ( !persister.isInstance( object, session.getEntityMode() ) ) { 1177 throw new WrongClassException( 1178 "loaded object was of wrong class", 1179 key.getIdentifier(), 1180 persister.getEntityName() 1181 ); 1182 } 1183 1184 if ( LockMode.NONE != lockMode && upgradeLocks() ) { 1186 final boolean isVersionCheckNeeded = persister.isVersioned() && 1187 session.getPersistenceContext().getEntry(object) 1188 .getLockMode().lessThan( lockMode ); 1189 if (isVersionCheckNeeded) { 1193 checkVersion( i, persister, key.getIdentifier(), object, rs, session ); 1195 session.getPersistenceContext().getEntry(object) 1197 .setLockMode(lockMode); 1198 } 1199 } 1200 } 1201 1202 1205 private Object instanceNotYetLoaded( 1206 final ResultSet rs, 1207 final int i, 1208 final Loadable persister, 1209 final String rowIdAlias, 1210 final EntityKey key, 1211 final LockMode lockMode, 1212 final EntityKey optionalObjectKey, 1213 final Object optionalObject, 1214 final List hydratedObjects, 1215 final SessionImplementor session) 1216 throws HibernateException, SQLException { 1217 1218 final String instanceClass = getInstanceClass( 1219 rs, 1220 i, 1221 persister, 1222 key.getIdentifier(), 1223 session 1224 ); 1225 1226 final Object object; 1227 if ( optionalObjectKey != null && key.equals( optionalObjectKey ) ) { 1228 object = optionalObject; 1230 } 1231 else { 1232 object = session.instantiate( instanceClass, key.getIdentifier() ); 1234 } 1235 1236 1238 LockMode acquiredLockMode = lockMode == LockMode.NONE ? LockMode.READ : lockMode; 1242 loadFromResultSet( 1243 rs, 1244 i, 1245 object, 1246 instanceClass, 1247 key, 1248 rowIdAlias, 1249 acquiredLockMode, 1250 persister, 1251 session 1252 ); 1253 1254 hydratedObjects.add( object ); 1256 1257 return object; 1258 } 1259 1260 private boolean isEagerPropertyFetchEnabled(int i) { 1261 boolean[] array = getEntityEagerPropertyFetches(); 1262 return array!=null && array[i]; 1263 } 1264 1265 1266 1271 private void loadFromResultSet( 1272 final ResultSet rs, 1273 final int i, 1274 final Object object, 1275 final String instanceEntityName, 1276 final EntityKey key, 1277 final String rowIdAlias, 1278 final LockMode lockMode, 1279 final Loadable rootPersister, 1280 final SessionImplementor session) 1281 throws SQLException , HibernateException { 1282 1283 final Serializable id = key.getIdentifier(); 1284 1285 final Loadable persister = (Loadable) getFactory().getEntityPersister( instanceEntityName ); 1287 1288 if ( log.isTraceEnabled() ) { 1289 log.trace( 1290 "Initializing object from ResultSet: " + 1291 MessageHelper.infoString( persister, id, getFactory() ) 1292 ); 1293 } 1294 1295 boolean eagerPropertyFetch = isEagerPropertyFetchEnabled(i); 1296 1297 TwoPhaseLoad.addUninitializedEntity( 1301 key, 1302 object, 1303 persister, 1304 lockMode, 1305 !eagerPropertyFetch, 1306 session 1307 ); 1308 1309 final String [][] cols = persister == rootPersister ? 1311 getEntityAliases()[i].getSuffixedPropertyAliases() : 1312 getEntityAliases()[i].getSuffixedPropertyAliases(persister); 1313 1314 final Object [] values = persister.hydrate( 1315 rs, 1316 id, 1317 object, 1318 rootPersister, 1319 cols, 1320 eagerPropertyFetch, 1321 session 1322 ); 1323 1324 final Object rowId = persister.hasRowId() ? rs.getObject(rowIdAlias) : null; 1325 1326 final AssociationType[] ownerAssociationTypes = getOwnerAssociationTypes(); 1327 if ( ownerAssociationTypes != null && ownerAssociationTypes[i] != null ) { 1328 String ukName = ownerAssociationTypes[i].getRHSUniqueKeyPropertyName(); 1329 if (ukName!=null) { 1330 final int index = ( (UniqueKeyLoadable) persister ).getPropertyIndex(ukName); 1331 final Type type = persister.getPropertyTypes()[index]; 1332 1333 1338 EntityUniqueKey euk = new EntityUniqueKey( 1339 rootPersister.getEntityName(), ukName, 1341 type.semiResolve( values[index], session, object ), 1342 type, 1343 session.getEntityMode(), session.getFactory() 1344 ); 1345 session.getPersistenceContext().addEntity( euk, object ); 1346 } 1347 } 1348 1349 TwoPhaseLoad.postHydrate( 1350 persister, 1351 id, 1352 values, 1353 rowId, 1354 object, 1355 lockMode, 1356 !eagerPropertyFetch, 1357 session 1358 ); 1359 1360 } 1361 1362 1365 private String getInstanceClass( 1366 final ResultSet rs, 1367 final int i, 1368 final Loadable persister, 1369 final Serializable id, 1370 final SessionImplementor session) 1371 throws HibernateException, SQLException { 1372 1373 if ( persister.hasSubclasses() ) { 1374 1375 Object discriminatorValue = persister.getDiscriminatorType().nullSafeGet( 1377 rs, 1378 getEntityAliases()[i].getSuffixedDiscriminatorAlias(), 1379 session, 1380 null 1381 ); 1382 1383 final String result = persister.getSubclassForDiscriminatorValue( discriminatorValue ); 1384 1385 if ( result == null ) { 1386 throw new WrongClassException( 1388 "Discriminator: " + discriminatorValue, 1389 id, 1390 persister.getEntityName() 1391 ); 1392 } 1393 1394 return result; 1395 1396 } 1397 else { 1398 return persister.getEntityName(); 1399 } 1400 } 1401 1402 1405 private void advance(final ResultSet rs, final RowSelection selection) 1406 throws SQLException { 1407 1408 final int firstRow = getFirstRow( selection ); 1409 if ( firstRow != 0 ) { 1410 if ( getFactory().getSettings().isScrollableResultSetsEnabled() ) { 1411 rs.absolute( firstRow ); 1413 } 1414 else { 1415 for ( int m = 0; m < firstRow; m++ ) rs.next(); 1417 } 1418 } 1419 } 1420 1421 private static boolean hasMaxRows(RowSelection selection) { 1422 return selection != null && selection.getMaxRows() != null; 1423 } 1424 1425 private static int getFirstRow(RowSelection selection) { 1426 if ( selection == null || selection.getFirstRow() == null ) { 1427 return 0; 1428 } 1429 else { 1430 return selection.getFirstRow().intValue(); 1431 } 1432 } 1433 1434 1438 private static boolean useLimit(final RowSelection selection, final Dialect dialect) { 1439 return dialect.supportsLimit() && hasMaxRows( selection ); 1440 } 1441 1442 1446 protected int bindPositionalParameters( 1447 final PreparedStatement st, 1448 final QueryParameters queryParameters, 1449 final int start, 1450 final SessionImplementor session) throws SQLException , HibernateException { 1451 1452 final Object [] values = queryParameters.getFilteredPositionalParameterValues(); 1453 final Type[] types = queryParameters.getFilteredPositionalParameterTypes(); 1454 int span = 0; 1455 for ( int i = 0; i < values.length; i++ ) { 1456 types[i].nullSafeSet( st, values[i], start + span, session ); 1457 span += types[i].getColumnSpan( getFactory() ); 1458 } 1459 return span; 1460 } 1461 1462 1467 protected final PreparedStatement prepareQueryStatement( 1468 final QueryParameters queryParameters, 1469 final boolean scroll, 1470 final SessionImplementor session) throws SQLException , HibernateException { 1471 1472 queryParameters.processFilters( getSQLString(), session ); 1473 String sql = queryParameters.getFilteredSQL(); 1474 final Dialect dialect = getFactory().getDialect(); 1475 final RowSelection selection = queryParameters.getRowSelection(); 1476 boolean useLimit = useLimit( selection, dialect ); 1477 boolean hasFirstRow = getFirstRow( selection ) > 0; 1478 boolean useOffset = hasFirstRow && useLimit && dialect.supportsLimitOffset(); 1479 boolean callable = queryParameters.isCallable(); 1480 1481 boolean useScrollableResultSetToSkip = hasFirstRow && 1482 !useOffset && 1483 getFactory().getSettings().isScrollableResultSetsEnabled(); 1484 ScrollMode scrollMode = scroll ? queryParameters.getScrollMode() : ScrollMode.SCROLL_INSENSITIVE; 1485 1486 if ( useLimit ) { 1487 sql = dialect.getLimitString( 1488 sql.trim(), useOffset ? getFirstRow(selection) : 0, 1490 getMaxOrLimit(selection, dialect) 1491 ); 1492 } 1493 1494 sql = preprocessSQL( sql, queryParameters, dialect ); 1495 1496 PreparedStatement st = null; 1497 1498 if (callable) { 1499 st = session.getBatcher() 1500 .prepareCallableQueryStatement( sql, scroll || useScrollableResultSetToSkip, scrollMode ); 1501 } 1502 else { 1503 st = session.getBatcher() 1504 .prepareQueryStatement( sql, scroll || useScrollableResultSetToSkip, scrollMode ); 1505 } 1506 1507 1508 try { 1509 1510 int col = 1; 1511 if ( useLimit && dialect.bindLimitParametersFirst() ) { 1513 col += bindLimitParameters( st, col, selection ); 1514 } 1515 if (callable) { 1516 col = dialect.registerResultSetOutParameter( (CallableStatement )st, col ); 1517 } 1518 col += bindPositionalParameters( st, queryParameters, col, session ); 1519 col += bindNamedParameters( st, queryParameters.getNamedParameters(), col, session ); 1520 1521 if ( useLimit && !dialect.bindLimitParametersFirst() ) { 1522 col += bindLimitParameters( st, col, selection ); 1523 } 1524 1525 if ( !useLimit ) setMaxRows( st, selection ); 1526 if ( selection != null ) { 1527 if ( selection.getTimeout() != null ) { 1528 st.setQueryTimeout( selection.getTimeout().intValue() ); 1529 } 1530 if ( selection.getFetchSize() != null ) { 1531 st.setFetchSize( selection.getFetchSize().intValue() ); 1532 } 1533 } 1534 } 1535 catch ( SQLException sqle ) { 1536 session.getBatcher().closeQueryStatement( st, null ); 1537 throw sqle; 1538 } 1539 catch ( HibernateException he ) { 1540 session.getBatcher().closeQueryStatement( st, null ); 1541 throw he; 1542 } 1543 1544 return st; 1545 } 1546 1547 1551 private static int getMaxOrLimit(final RowSelection selection, final Dialect dialect) { 1552 final int firstRow = getFirstRow( selection ); 1553 final int lastRow = selection.getMaxRows().intValue(); 1554 if ( dialect.useMaxForLimit() ) { 1555 return lastRow + firstRow; 1556 } 1557 else { 1558 return lastRow; 1559 } 1560 } 1561 1562 1565 private int bindLimitParameters(final PreparedStatement st, final int index, final RowSelection selection) 1566 throws SQLException { 1567 1568 Dialect dialect = getFactory().getDialect(); 1569 if ( !dialect.supportsVariableLimit() ) return 0; 1570 if ( !hasMaxRows( selection ) ) { 1571 throw new AssertionFailure( "no max results set" ); 1572 } 1573 int firstRow = getFirstRow( selection ); 1574 int lastRow = getMaxOrLimit( selection, dialect ); 1575 boolean hasFirstRow = firstRow > 0 && dialect.supportsLimitOffset(); 1576 boolean reverse = dialect.bindLimitParametersInReverseOrder(); 1577 if ( hasFirstRow ) st.setInt( index + ( reverse ? 1 : 0 ), firstRow ); 1578 st.setInt( index + ( reverse || !hasFirstRow ? 0 : 1 ), lastRow ); 1579 return hasFirstRow ? 2 : 1; 1580 } 1581 1582 1585 private void setMaxRows(final PreparedStatement st, final RowSelection selection) 1586 throws SQLException { 1587 if ( hasMaxRows( selection ) ) { 1588 st.setMaxRows( selection.getMaxRows().intValue() + getFirstRow( selection ) ); 1589 } 1590 } 1591 1592 protected final ResultSet getResultSet( 1593 final PreparedStatement st, 1594 final RowSelection selection, 1595 final SessionImplementor session) 1596 throws HibernateException, SQLException { 1597 return getResultSet(st, false, selection, session); 1598 } 1599 1600 1604 protected final ResultSet getResultSet( 1605 final PreparedStatement st, 1606 final boolean callable, 1607 final RowSelection selection, 1608 final SessionImplementor session) 1609 throws SQLException , HibernateException { 1610 1611 ResultSet rs = null; 1612 try { 1613 Dialect dialect = getFactory().getDialect(); 1614 if (callable) { 1615 rs = session.getBatcher().getResultSet( (CallableStatement ) st, dialect ); 1616 } 1617 else { 1618 rs = session.getBatcher().getResultSet( st ); 1619 } 1620 rs = wrapResultSetIfEnabled( rs , session ); 1621 if ( !dialect.supportsLimitOffset() || !useLimit( selection, dialect ) ) { 1622 advance( rs, selection ); 1623 } 1624 return rs; 1625 } 1626 catch ( SQLException sqle ) { 1627 session.getBatcher().closeQueryStatement( st, rs ); 1628 throw sqle; 1629 } 1630 } 1631 1632 private synchronized ResultSet wrapResultSetIfEnabled(final ResultSet rs, final SessionImplementor session) { 1633 if ( session.getFactory().getSettings().isWrapResultSetsEnabled() ) { 1636 try { 1637 log.debug("Wrapping result set [" + rs + "]"); 1638 return new ResultSetWrapper( rs, retreiveColumnNameToIndexCache( rs ) ); 1639 } 1640 catch(SQLException e) { 1641 log.info("Error wrapping result set", e); 1642 return rs; 1643 } 1644 } 1645 else { 1646 return rs; 1647 } 1648 } 1649 1650 private ColumnNameCache retreiveColumnNameToIndexCache(ResultSet rs) throws SQLException { 1651 if ( columnNameCache == null ) { 1652 log.trace("Building columnName->columnIndex cache"); 1653 columnNameCache = new ColumnNameCache( rs.getMetaData().getColumnCount() ); 1654 } 1655 1656 return columnNameCache; 1657 } 1658 1659 1664 protected int bindNamedParameters( 1665 PreparedStatement st, 1666 Map namedParams, 1667 int start, 1668 SessionImplementor session) 1669 throws SQLException , HibernateException { 1670 return 0; 1671 } 1672 1673 1677 protected final List loadEntity( 1678 final SessionImplementor session, 1679 final Object id, 1680 final Type identifierType, 1681 final Object optionalObject, 1682 final String optionalEntityName, 1683 final Serializable optionalIdentifier, 1684 final EntityPersister persister) throws HibernateException { 1685 1686 if ( log.isDebugEnabled() ) { 1687 log.debug( 1688 "loading entity: " + 1689 MessageHelper.infoString( persister, id, identifierType, getFactory() ) 1690 ); 1691 } 1692 1693 List result; 1694 try { 1695 result = doQueryAndInitializeNonLazyCollections( 1696 session, 1697 new QueryParameters( 1698 new Type[]{identifierType}, 1699 new Object []{id}, 1700 optionalObject, 1701 optionalEntityName, 1702 optionalIdentifier 1703 ), 1704 false 1705 ); 1706 } 1707 catch ( SQLException sqle ) { 1708 final Loadable[] persisters = getEntityPersisters(); 1709 throw JDBCExceptionHelper.convert( 1710 factory.getSQLExceptionConverter(), 1711 sqle, 1712 "could not load an entity: " + 1713 MessageHelper.infoString( persisters[persisters.length-1], id, identifierType, getFactory() ), 1714 getSQLString() 1715 ); 1716 } 1717 1718 log.debug("done entity load"); 1719 1720 return result; 1721 1722 } 1723 1724 1728 public final List loadEntityBatch( 1729 final SessionImplementor session, 1730 final Serializable [] ids, 1731 final Type idType, 1732 final Object optionalObject, 1733 final String optionalEntityName, 1734 final Serializable optionalId, 1735 final EntityPersister persister) throws HibernateException { 1736 1737 if ( log.isDebugEnabled() ) { 1738 log.debug( 1739 "batch loading entity: " + 1740 MessageHelper.infoString(persister, ids, getFactory() ) 1741 ); 1742 } 1743 1744 Type[] types = new Type[ids.length]; 1745 Arrays.fill( types, idType ); 1746 List result; 1747 try { 1748 result = doQueryAndInitializeNonLazyCollections( 1749 session, 1750 new QueryParameters( types, ids, optionalObject, optionalEntityName, optionalId ), 1751 false 1752 ); 1753 } 1754 catch ( SQLException sqle ) { 1755 throw JDBCExceptionHelper.convert( 1756 factory.getSQLExceptionConverter(), 1757 sqle, 1758 "could not load an entity batch: " + 1759 MessageHelper.infoString( getEntityPersisters()[0], ids, getFactory() ), 1760 getSQLString() 1761 ); 1762 } 1763 1764 log.debug("done entity batch load"); 1765 1766 return result; 1767 1768 } 1769 1770 1773 public final void loadCollection( 1774 final SessionImplementor session, 1775 final Serializable id, 1776 final Type type) throws HibernateException { 1777 1778 if ( log.isDebugEnabled() ) { 1779 log.debug( 1780 "loading collection: "+ 1781 MessageHelper.collectionInfoString( getCollectionPersisters()[0], id, getFactory() ) 1782 ); 1783 } 1784 1785 Serializable [] ids = new Serializable []{id}; 1786 try { 1787 doQueryAndInitializeNonLazyCollections( 1788 session, 1789 new QueryParameters( new Type[]{type}, ids, ids ), 1790 true 1791 ); 1792 } 1793 catch ( SQLException sqle ) { 1794 throw JDBCExceptionHelper.convert( 1795 factory.getSQLExceptionConverter(), 1796 sqle, 1797 "could not initialize a collection: " + 1798 MessageHelper.collectionInfoString( getCollectionPersisters()[0], id, getFactory() ), 1799 getSQLString() 1800 ); 1801 } 1802 1803 log.debug("done loading collection"); 1804 1805 } 1806 1807 1810 public final void loadCollectionBatch( 1811 final SessionImplementor session, 1812 final Serializable [] ids, 1813 final Type type) throws HibernateException { 1814 1815 if ( log.isDebugEnabled() ) { 1816 log.debug( 1817 "batch loading collection: "+ 1818 MessageHelper.collectionInfoString( getCollectionPersisters()[0], ids, getFactory() ) 1819 ); 1820 } 1821 1822 Type[] idTypes = new Type[ids.length]; 1823 Arrays.fill( idTypes, type ); 1824 try { 1825 doQueryAndInitializeNonLazyCollections( 1826 session, 1827 new QueryParameters( idTypes, ids, ids ), 1828 true 1829 ); 1830 } 1831 catch ( SQLException sqle ) { 1832 throw JDBCExceptionHelper.convert( 1833 factory.getSQLExceptionConverter(), 1834 sqle, 1835 "could not initialize a collection batch: " + 1836 MessageHelper.collectionInfoString( getCollectionPersisters()[0], ids, getFactory() ), 1837 getSQLString() 1838 ); 1839 } 1840 1841 log.debug("done batch load"); 1842 1843 } 1844 1845 1848 protected final void loadCollectionSubselect( 1849 final SessionImplementor session, 1850 final Serializable [] ids, 1851 final Object [] parameterValues, 1852 final Type[] parameterTypes, 1853 final Map namedParameters, 1854 final Type type) throws HibernateException { 1855 1856 Type[] idTypes = new Type[ids.length]; 1857 Arrays.fill( idTypes, type ); 1858 try { 1859 doQueryAndInitializeNonLazyCollections( session, 1860 new QueryParameters( parameterTypes, parameterValues, namedParameters, ids ), 1861 true 1862 ); 1863 } 1864 catch ( SQLException sqle ) { 1865 throw JDBCExceptionHelper.convert( 1866 factory.getSQLExceptionConverter(), 1867 sqle, 1868 "could not load collection by subselect: " + 1869 MessageHelper.collectionInfoString( getCollectionPersisters()[0], ids, getFactory() ), 1870 getSQLString() 1871 ); 1872 } 1873 } 1874 1875 1879 protected List list( 1880 final SessionImplementor session, 1881 final QueryParameters queryParameters, 1882 final Set querySpaces, 1883 final Type[] resultTypes) throws HibernateException { 1884 1885 final boolean cacheable = factory.getSettings().isQueryCacheEnabled() && 1886 queryParameters.isCacheable(); 1887 1888 if ( cacheable ) { 1889 1890 final boolean queryStatisticsEnabled = factory.getStatistics().isStatisticsEnabled(); 1891 1892 QueryCache queryCache = factory.getQueryCache( queryParameters.getCacheRegion() ); 1893 Set filterKeys = FilterKey.createFilterKeys( 1894 session.getEnabledFilters(), 1895 session.getEntityMode() 1896 ); 1897 QueryKey key = new QueryKey( 1898 getSQLString(), 1899 queryParameters, 1900 filterKeys, 1901 session.getEntityMode() 1902 ); 1903 List result = null; 1904 1905 if ( session.getCacheMode().isGetEnabled() ) { 1906 result = queryCache.get( 1907 key, 1908 resultTypes, 1909 queryParameters.isNaturalKeyLookup(), 1910 querySpaces, 1911 session 1912 ); 1913 1914 if (queryStatisticsEnabled) { 1915 if (result==null) { 1916 factory.getStatisticsImplementor() 1917 .queryCacheMiss( getQueryIdentifier(), queryCache.getRegionName() ); 1918 } 1919 else { 1920 factory.getStatisticsImplementor() 1921 .queryCacheHit( getQueryIdentifier(), queryCache.getRegionName() ); 1922 } 1923 } 1924 } 1925 1926 1927 if ( result == null ) { 1928 result = doList( session, queryParameters ); 1929 1930 if ( cacheable && session.getCacheMode().isPutEnabled() ) { 1931 queryCache.put( key, resultTypes, result, session ); 1932 1933 if ( queryStatisticsEnabled ) { 1934 factory.getStatisticsImplementor() 1935 .queryCachePut( getQueryIdentifier(), queryCache.getRegionName() ); 1936 } 1937 } 1938 } 1939 1940 return getResultList( result ); 1941 } 1942 else { 1943 return getResultList( doList( session, queryParameters ) ); 1944 } 1945 } 1946 1947 1950 protected List doList(final SessionImplementor session, final QueryParameters queryParameters) 1951 throws HibernateException { 1952 1953 final boolean stats = getFactory().getStatistics().isStatisticsEnabled(); 1954 long startTime = 0; 1955 if ( stats ) startTime = System.currentTimeMillis(); 1956 1957 List result; 1958 try { 1959 result = doQueryAndInitializeNonLazyCollections( session, queryParameters, true ); 1960 } 1961 catch ( SQLException sqle ) { 1962 throw JDBCExceptionHelper.convert( 1963 factory.getSQLExceptionConverter(), 1964 sqle, 1965 "could not execute query", 1966 getSQLString() 1967 ); 1968 } 1969 1970 if ( stats ) { 1971 getFactory().getStatisticsImplementor().queryExecuted( 1972 getQueryIdentifier(), 1973 result.size(), 1974 System.currentTimeMillis() - startTime ); 1975 } 1976 1977 return result; 1978 } 1979 1980 1985 protected void checkScrollability() throws HibernateException { 1986 return; 1991 } 1992 1993 1999 protected boolean needsFecthingScroll() { 2000 return false; 2001 } 2002 2003 2015 protected ScrollableResults scroll( 2016 final QueryParameters queryParameters, 2017 final Type[] returnTypes, 2018 final HolderInstantiator holderInstantiator, 2019 final SessionImplementor session) throws HibernateException { 2020 2021 checkScrollability(); 2022 2023 final boolean stats = getQueryIdentifier() != null && 2024 getFactory().getStatistics().isStatisticsEnabled(); 2025 long startTime = 0; 2026 if ( stats ) startTime = System.currentTimeMillis(); 2027 2028 try { 2029 2030 PreparedStatement st = prepareQueryStatement( queryParameters, true, session ); 2031 ResultSet rs = getResultSet( st, queryParameters.getRowSelection(), session ); 2032 2033 if ( stats ) { 2034 getFactory().getStatisticsImplementor().queryExecuted( 2035 getQueryIdentifier(), 2036 0, 2037 System.currentTimeMillis() - startTime 2038 ); 2039 } 2040 2041 if ( needsFecthingScroll() ) { 2042 return new FetchingScrollableResultsImpl( 2043 rs, 2044 st, 2045 session, 2046 this, 2047 queryParameters, 2048 returnTypes, 2049 holderInstantiator 2050 ); 2051 } 2052 else { 2053 return new ScrollableResultsImpl( 2054 rs, 2055 st, 2056 session, 2057 this, 2058 queryParameters, 2059 returnTypes, 2060 holderInstantiator 2061 ); 2062 } 2063 2064 } 2065 catch ( SQLException sqle ) { 2066 throw JDBCExceptionHelper.convert( 2067 factory.getSQLExceptionConverter(), 2068 sqle, 2069 "could not execute query using scroll", 2070 getSQLString() 2071 ); 2072 } 2073 2074 } 2075 2076 2080 protected void postInstantiate() {} 2081 2082 2085 protected abstract EntityAliases[] getEntityAliases(); 2086 2087 protected abstract CollectionAliases[] getCollectionAliases(); 2088 2089 2093 protected String getQueryIdentifier() { 2094 return null; 2095 } 2096 2097 public final SessionFactoryImplementor getFactory() { 2098 return factory; 2099 } 2100 2101 public String toString() { 2102 return getClass().getName() + '(' + getSQLString() + ')'; 2103 } 2104 2105} 2106 | Popular Tags |