| 1 package org.hibernate.impl; 3 4 import java.io.IOException ; 5 import java.io.ObjectInputStream ; 6 import java.io.ObjectOutputStream ; 7 import java.io.Serializable ; 8 import java.sql.Connection ; 9 import java.util.Collection ; 10 import java.util.Collections ; 11 import java.util.HashMap ; 12 import java.util.HashSet ; 13 import java.util.Iterator ; 14 import java.util.List ; 15 import java.util.Map ; 16 import java.util.Set ; 17 18 import org.apache.commons.logging.Log; 19 import org.apache.commons.logging.LogFactory; 20 import org.dom4j.Element; 21 import org.hibernate.CacheMode; 22 import org.hibernate.ConnectionReleaseMode; 23 import org.hibernate.Criteria; 24 import org.hibernate.EntityMode; 25 import org.hibernate.Filter; 26 import org.hibernate.FlushMode; 27 import org.hibernate.HibernateException; 28 import org.hibernate.Interceptor; 29 import org.hibernate.LockMode; 30 import org.hibernate.MappingException; 31 import org.hibernate.ObjectDeletedException; 32 import org.hibernate.ObjectNotFoundException; 33 import org.hibernate.Query; 34 import org.hibernate.QueryException; 35 import org.hibernate.ReplicationMode; 36 import org.hibernate.SQLQuery; 37 import org.hibernate.ScrollMode; 38 import org.hibernate.ScrollableResults; 39 import org.hibernate.Session; 40 import org.hibernate.SessionFactory; 41 import org.hibernate.Transaction; 42 import org.hibernate.TransientObjectException; 43 import org.hibernate.UnresolvableObjectException; 44 import org.hibernate.collection.PersistentCollection; 45 import org.hibernate.engine.ActionQueue; 46 import org.hibernate.engine.CollectionEntry; 47 import org.hibernate.engine.EntityEntry; 48 import org.hibernate.engine.EntityKey; 49 import org.hibernate.engine.FilterDefinition; 50 import org.hibernate.engine.PersistenceContext; 51 import org.hibernate.engine.QueryParameters; 52 import org.hibernate.engine.SessionFactoryImplementor; 53 import org.hibernate.engine.StatefulPersistenceContext; 54 import org.hibernate.engine.Status; 55 import org.hibernate.event.AutoFlushEvent; 56 import org.hibernate.event.DeleteEvent; 57 import org.hibernate.event.DirtyCheckEvent; 58 import org.hibernate.event.EventSource; 59 import org.hibernate.event.EvictEvent; 60 import org.hibernate.event.FlushEvent; 61 import org.hibernate.event.InitializeCollectionEvent; 62 import org.hibernate.event.LoadEvent; 63 import org.hibernate.event.LoadEventListener; 64 import org.hibernate.event.LockEvent; 65 import org.hibernate.event.MergeEvent; 66 import org.hibernate.event.PersistEvent; 67 import org.hibernate.event.RefreshEvent; 68 import org.hibernate.event.ReplicateEvent; 69 import org.hibernate.event.SaveOrUpdateEvent; 70 import org.hibernate.event.SessionEventListenerConfig; 71 import org.hibernate.hql.FilterTranslator; 72 import org.hibernate.hql.QuerySplitter; 73 import org.hibernate.hql.QueryTranslator; 74 import org.hibernate.jdbc.Batcher; 75 import org.hibernate.jdbc.JDBCContext; 76 import org.hibernate.loader.criteria.CriteriaLoader; 77 import org.hibernate.loader.custom.CustomLoader; 78 import org.hibernate.loader.custom.CustomQuery; 79 import org.hibernate.persister.collection.CollectionPersister; 80 import org.hibernate.persister.entity.EntityPersister; 81 import org.hibernate.persister.entity.OuterJoinLoadable; 82 import org.hibernate.pretty.MessageHelper; 83 import org.hibernate.proxy.HibernateProxy; 84 import org.hibernate.proxy.LazyInitializer; 85 import org.hibernate.stat.SessionStatistics; 86 import org.hibernate.stat.SessionStatisticsImpl; 87 import org.hibernate.tuple.DynamicMapInstantiator; 88 import org.hibernate.type.Type; 89 import org.hibernate.util.ArrayHelper; 90 import org.hibernate.util.CollectionHelper; 91 import org.hibernate.util.EmptyIterator; 92 import org.hibernate.util.JoinedIterator; 93 import org.hibernate.util.StringHelper; 94 95 96 104 public final class SessionImpl extends AbstractSessionImpl 105 implements EventSource, org.hibernate.classic.Session, JDBCContext.Context { 106 107 111 private static final Log log = LogFactory.getLog(SessionImpl.class); 112 113 private EntityMode entityMode = EntityMode.POJO; 114 private boolean autoClear; 116 private final long timestamp; 117 private boolean closed = false; 118 private FlushMode flushMode = FlushMode.AUTO; 119 private CacheMode cacheMode = CacheMode.NORMAL; 120 121 private Interceptor interceptor; 122 123 private transient int dontFlushFromFind = 0; 124 125 private ActionQueue actionQueue; 126 private StatefulPersistenceContext persistenceContext; 127 private transient JDBCContext jdbcContext; 128 private SessionEventListenerConfig listeners; 129 130 private final boolean flushBeforeCompletionEnabled; 131 private final boolean autoCloseSessionEnabled; 132 private final ConnectionReleaseMode connectionReleaseMode; 133 134 private Map enabledFilters = new HashMap (); 135 136 private boolean isRootSession = true; 137 private Map childSessionsByEntityMode; 138 139 140 public Session getSession(EntityMode entityMode) { 141 if ( this.entityMode == entityMode ) { 142 return this; 143 } 144 145 if ( childSessionsByEntityMode == null ) { 146 childSessionsByEntityMode = new HashMap (); 147 } 148 149 SessionImpl rtn = (SessionImpl) childSessionsByEntityMode.get( entityMode ); 150 if ( rtn == null ) { 151 rtn = new SessionImpl( this, entityMode ); 152 childSessionsByEntityMode.put( entityMode, rtn ); 153 } 154 155 return rtn; 156 } 157 158 159 private void readObject(ObjectInputStream ois) throws IOException , ClassNotFoundException { 160 log.trace("deserializing session"); 161 162 interceptor = (Interceptor) ois.readObject(); 163 factory = (SessionFactoryImpl) ois.readObject(); 164 jdbcContext = (JDBCContext) ois.readObject(); 165 ois.defaultReadObject(); 166 167 Iterator iter = enabledFilters.values().iterator(); 168 while ( iter.hasNext() ) { 169 ( (FilterImpl) iter.next() ).afterDeserialize(factory); 170 } 171 } 172 173 private void writeObject(ObjectOutputStream oos) throws IOException { 174 if ( jdbcContext.getConnectionManager().isPhysicallyConnected() ) { 175 throw new IllegalStateException ( "Cannot serialize a session while connected" ); 176 } 177 178 log.trace( "serializing session" ); 179 180 oos.writeObject(interceptor); 181 oos.writeObject(factory); 182 oos.writeObject(jdbcContext); 183 oos.defaultWriteObject(); 184 185 } 186 187 public void clear() { 188 persistenceContext.clear(); 189 actionQueue.clear(); 190 } 191 192 private SessionImpl(SessionImpl parent, EntityMode entityMode) { 193 super(parent.factory); 194 195 this.timestamp = parent.timestamp; 196 197 this.jdbcContext = parent.jdbcContext; 198 199 this.interceptor = parent.interceptor; 200 this.listeners = parent.listeners; 201 202 this.actionQueue = new ActionQueue(this); 203 204 this.entityMode = entityMode; 205 this.persistenceContext = new StatefulPersistenceContext(this); 206 207 this.flushBeforeCompletionEnabled = false; 208 this.autoCloseSessionEnabled = false; 209 this.connectionReleaseMode = null; 210 211 this.isRootSession = false; 212 213 if ( factory.getStatistics().isStatisticsEnabled() ) { 214 factory.getStatisticsImplementor().openSession(); 215 } 216 217 log.debug( "opened session [" + entityMode + "]" ); 218 } 219 220 SessionImpl( 221 final Connection connection, 222 final SessionFactoryImpl factory, 223 final boolean autoclose, 224 final long timestamp, 225 final Interceptor interceptor, 226 final SessionEventListenerConfig listeners, 227 final EntityMode entityMode, 228 final boolean flushBeforeCompletionEnabled, 229 final boolean autoCloseSessionEnabled, 230 final ConnectionReleaseMode connectionReleaseMode) { 231 super(factory); 232 233 this.timestamp = timestamp; 234 235 this.entityMode = entityMode; 236 237 this.interceptor = interceptor; 238 this.listeners = listeners; 239 240 this.actionQueue = new ActionQueue( this ); 241 this.persistenceContext = new StatefulPersistenceContext( this ); 242 243 this.isRootSession = true; 244 245 this.flushBeforeCompletionEnabled = flushBeforeCompletionEnabled; 246 this.autoCloseSessionEnabled = autoCloseSessionEnabled; 247 this.connectionReleaseMode = connectionReleaseMode; 248 249 this.jdbcContext = new JDBCContext( this, connection ); 250 251 if ( factory.getStatistics().isStatisticsEnabled() ) { 252 factory.getStatisticsImplementor().openSession(); 253 } 254 255 if ( log.isDebugEnabled() ) log.debug( "opened session at timestamp: " + timestamp ); 256 } 257 258 public Batcher getBatcher() { 259 return jdbcContext.getConnectionManager().getBatcher(); 262 } 263 264 public SessionFactoryImplementor getFactory() { 265 return factory; 266 } 267 268 public long getTimestamp() { 269 return timestamp; 270 } 271 272 public Connection close() throws HibernateException { 273 274 log.trace( "closing session" ); 275 276 if ( factory.getStatistics().isStatisticsEnabled() ) 277 factory.getStatisticsImplementor().closeSession(); 278 279 try { 280 try { 281 if ( childSessionsByEntityMode != null ) { 282 Iterator childSessions = childSessionsByEntityMode.values().iterator(); 283 while ( childSessions.hasNext() ) { 284 final SessionImpl child = ( SessionImpl ) childSessions.next(); 285 child.close(); 286 } 287 } 288 } 289 catch( Throwable t ) { 290 } 292 293 if ( isRootSession ) { 294 return jdbcContext.getConnectionManager().close(); 295 } 296 else { 297 return null; 298 } 299 } 300 finally { 301 closed = true; 302 cleanup(); 303 } 304 } 305 306 public ConnectionReleaseMode getConnectionReleaseMode() { 307 return connectionReleaseMode; 308 } 309 310 public boolean isAutoCloseSessionEnabled() { 311 return autoCloseSessionEnabled; 312 } 313 314 public boolean isOpen() { 315 return !closed; 316 } 317 318 public boolean isFlushModeNever() { 319 return getFlushMode() == FlushMode.NEVER; 320 } 321 322 public boolean isFlushBeforeCompletionEnabled() { 323 return flushBeforeCompletionEnabled; 324 } 325 326 public void managedFlush() { 327 328 log.trace("automatically flushing session"); 329 flush(); 330 331 if ( childSessionsByEntityMode != null ) { 332 Iterator iter = childSessionsByEntityMode.values().iterator(); 333 while ( iter.hasNext() ) { 334 ( (Session) iter.next() ).flush(); 335 } 336 } 337 338 } 339 340 public boolean shouldAutoClose() { 341 return isAutoCloseSessionEnabled() && isOpen(); 342 } 343 344 public void managedClose() { 345 log.trace("automatically closing session"); 346 close(); 347 } 348 349 public Connection connection() throws HibernateException { 350 return jdbcContext.connection(); 351 } 352 353 public boolean isConnected() { 354 return jdbcContext.getConnectionManager().isLogicallyConnected(); 355 } 356 357 public boolean isTransactionInProgress() { 358 return jdbcContext.isTransactionInProgress(); 359 } 360 361 public Connection disconnect() throws HibernateException { 362 log.debug( "disconnecting session" ); 363 return jdbcContext.getConnectionManager().manualDisconnect(); 364 } 365 366 public void reconnect() throws HibernateException { 367 log.debug( "reconnecting session" ); 368 jdbcContext.getConnectionManager().manualReconnect(); 369 } 370 371 public void reconnect(Connection conn) throws HibernateException { 372 log.debug( "reconnecting session" ); 373 jdbcContext.getConnectionManager().manualReconnect( conn ); 374 } 375 376 public void beforeTransactionCompletion(Transaction tx) { 377 log.trace( "before transaction completion" ); 378 379 if ( isRootSession ) { 380 381 try { 382 interceptor.beforeTransactionCompletion(tx); 383 } 384 catch (Throwable t) { 385 log.error("exception in interceptor beforeTransactionCompletion()", t); 386 } 387 388 } 389 } 390 391 public void setAutoClear(boolean enabled) { 392 autoClear = enabled; 393 } 394 395 401 public void afterOperation(boolean success) { 402 if ( !jdbcContext.isTransactionInProgress() ) { 403 jdbcContext.afterNontransactionalQuery(success); 404 } 405 } 406 407 public void afterTransactionCompletion(boolean success, Transaction tx) { 408 log.trace( "after transaction completion" ); 409 410 persistenceContext.afterTransactionCompletion(); 411 actionQueue.afterTransactionCompletion(success); 412 413 if ( isRootSession && tx!=null ) { 414 415 try { 416 interceptor.afterTransactionCompletion(tx); 417 } 418 catch (Throwable t) { 419 log.error("exception in interceptor beforeTransactionCompletion()", t); 420 } 421 422 } 423 424 if (autoClear) clear(); 425 426 } 427 428 434 private void cleanup() { 435 persistenceContext.clear(); 436 } 437 438 public LockMode getCurrentLockMode(Object object) throws HibernateException { 439 if ( object == null ) throw new NullPointerException ( "null object passed to getCurrentLockMode()" ); 440 if ( object instanceof HibernateProxy ) { 441 object = ( (HibernateProxy) object ).getHibernateLazyInitializer().getImplementation(this); 442 if ( object == null ) return LockMode.NONE; 443 } 444 EntityEntry e = persistenceContext.getEntry(object); 445 if ( e == null ) throw new TransientObjectException( "Given object not associated with the session" ); 446 if ( e.getStatus() != Status.MANAGED ) throw new ObjectDeletedException( 447 "The given object was deleted", 448 e.getId(), e.getPersister().getEntityName() 449 ); 450 return e.getLockMode(); 451 } 452 453 public Object getEntityUsingInterceptor(EntityKey key) throws HibernateException { 454 final Object result = persistenceContext.getEntity(key); 457 if ( result == null ) { 458 final Object newObject = interceptor.getEntity( key.getEntityName(), key.getIdentifier() ); 459 if ( newObject != null ) lock(newObject, LockMode.NONE); 460 return newObject; 461 } 462 else { 463 return result; 464 } 465 } 466 467 public void saveOrUpdate(Object object) throws HibernateException { 468 saveOrUpdate(null, object); 469 } 470 471 public void saveOrUpdate(String entityName, Object obj) throws HibernateException { 472 SaveOrUpdateEvent event = new SaveOrUpdateEvent(entityName, obj, this); 473 listeners.getSaveOrUpdateEventListener().onSaveOrUpdate(event); 474 } 475 476 public void save(Object obj, Serializable id) throws HibernateException { 477 save(null, obj, id); 478 } 479 480 public Serializable save(Object obj) throws HibernateException { 481 return save(null, obj); 482 } 483 484 public Serializable save(String entityName, Object object) throws HibernateException { 485 SaveOrUpdateEvent event = new SaveOrUpdateEvent(entityName, object, this); 486 return listeners.getSaveEventListener().onSaveOrUpdate(event); 487 } 488 489 public void save(String entityName, Object object, Serializable id) throws HibernateException { 490 SaveOrUpdateEvent event = new SaveOrUpdateEvent(entityName, object, id, this); 491 listeners.getSaveEventListener().onSaveOrUpdate(event); 492 } 493 494 public void update(Object obj) throws HibernateException { 495 update(null, obj); 496 } 497 498 public void update(Object obj, Serializable id) throws HibernateException { 499 update(null, obj, id); 500 } 501 502 public void update(String entityName, Object object) throws HibernateException { 503 SaveOrUpdateEvent event = new SaveOrUpdateEvent(entityName, object, this); 504 listeners.getUpdateEventListener().onSaveOrUpdate(event); 505 } 506 507 public void update(String entityName, Object object, Serializable id) throws HibernateException { 508 SaveOrUpdateEvent event = new SaveOrUpdateEvent(entityName, object, id, this); 509 listeners.getUpdateEventListener().onSaveOrUpdate(event); 510 } 511 512 public void lock(Object object, LockMode lockMode) throws HibernateException { 513 listeners.getLockEventListener().onLock( new LockEvent(object, lockMode, this) ); 514 } 515 516 public void lock(String entityName, Object object, LockMode lockMode) throws HibernateException { 517 LockEvent event = new LockEvent(entityName, object, lockMode, this); 518 listeners.getLockEventListener().onLock(event); 519 } 520 521 public void persist(String entityName, Object object, Map copiedAlready) 522 throws HibernateException { 523 PersistEvent event = new PersistEvent(entityName, object, this); 524 listeners.getCreateEventListener().onPersist(event, copiedAlready); 525 } 526 527 public void persist(String entityName, Object object) 528 throws HibernateException { 529 PersistEvent event = new PersistEvent(entityName, object, this); 530 listeners.getCreateEventListener().onPersist(event); 531 } 532 533 public void persist(Object object) throws HibernateException { 534 persist(null, object); 535 } 536 537 public Object merge(String entityName, Object object) 538 throws HibernateException { 539 MergeEvent event = new MergeEvent(entityName, object, this); 540 return listeners.getMergeEventListener().onMerge(event); 541 } 542 543 public Object merge(Object object) throws HibernateException { 544 return merge(null, object); 545 } 546 547 public void merge(String entityName, Object object, Map copiedAlready) throws HibernateException { 548 MergeEvent event = new MergeEvent(entityName, object, this); 549 listeners.getMergeEventListener().onMerge(event, copiedAlready); 550 } 551 552 public Object saveOrUpdateCopy(String entityName, Object object) 553 throws HibernateException { 554 MergeEvent event = new MergeEvent(entityName, object, this); 555 return listeners.getSaveOrUpdateCopyEventListener().onMerge(event); 556 } 557 558 public Object saveOrUpdateCopy(Object object) throws HibernateException { 559 return saveOrUpdateCopy(null, object); 560 } 561 562 public Object saveOrUpdateCopy(String entityName, Object object, Serializable id) 563 throws HibernateException { 564 MergeEvent event = new MergeEvent(entityName, object, id, this); 565 return listeners.getSaveOrUpdateCopyEventListener().onMerge(event); 566 } 567 568 public Object saveOrUpdateCopy(Object object, Serializable id) 569 throws HibernateException { 570 return saveOrUpdateCopy(null, object, id); 571 } 572 573 public void saveOrUpdateCopy(String entityName, Object object, Map copiedAlready) 574 throws HibernateException { 575 MergeEvent event = new MergeEvent(entityName, object, this); 576 listeners.getSaveOrUpdateCopyEventListener().onMerge(event, copiedAlready); 577 } 578 579 582 public void delete(Object object) throws HibernateException { 583 DeleteEvent event = new DeleteEvent(object, this); 584 listeners.getDeleteEventListener().onDelete(event); 585 } 586 587 590 public void delete(String entityName, Object object) throws HibernateException { 591 DeleteEvent event = new DeleteEvent( entityName, object, this ); 592 listeners.getDeleteEventListener().onDelete( event ); 593 } 594 595 598 public void delete(String entityName, Object object, boolean isCascadeDeleteEnabled) throws HibernateException { 599 DeleteEvent event = new DeleteEvent(entityName, object, isCascadeDeleteEnabled, this); 600 listeners.getDeleteEventListener().onDelete(event); 601 } 602 603 public void load(Object object, Serializable id) throws HibernateException { 604 LoadEvent event = new LoadEvent(id, object, this); 605 listeners.getLoadEventListener().onLoad(event, LoadEventListener.RELOAD); 606 } 607 608 public Object load(Class entityClass, Serializable id) throws HibernateException { 609 return load( entityClass.getName(), id ); 610 } 611 612 public Object load(String entityName, Serializable id) throws HibernateException { 613 LoadEvent event = new LoadEvent(id, entityName, false, this); 614 boolean success = false; 615 try { 616 Object result = listeners.getLoadEventListener().onLoad(event, LoadEventListener.LOAD); 617 ObjectNotFoundException.throwIfNull(result, id, entityName); 618 success = true; 619 return result; 620 } 621 finally { 622 afterOperation(success); 623 } 624 } 625 626 public Object get(Class entityClass, Serializable id) throws HibernateException { 627 return get( entityClass.getName(), id ); 628 } 629 630 public Object get(String entityName, Serializable id) throws HibernateException { 631 LoadEvent event = new LoadEvent(id, entityName, false, this); 632 boolean success = false; 633 try { 634 Object result = listeners.getLoadEventListener().onLoad(event, LoadEventListener.GET); 635 success = true; 636 return result; 637 } 638 finally { 639 afterOperation(success); 640 } 641 } 642 643 648 public Object immediateLoad(String entityName, Serializable id) throws HibernateException { 649 650 if ( log.isDebugEnabled() ) { 651 EntityPersister persister = getFactory().getEntityPersister(entityName); 652 log.debug( "initializing proxy: " + MessageHelper.infoString( persister, id, getFactory() ) ); 653 } 654 655 LoadEvent event = new LoadEvent(id, entityName, true, this); 656 Object result = listeners.getLoadEventListener().onLoad(event, LoadEventListener.IMMEDIATE_LOAD); 657 658 ObjectNotFoundException.throwIfNull(result, id, entityName); return result; 660 } 661 662 public Object internalLoad(String entityName, Serializable id, boolean eager, boolean nullable) throws HibernateException { 663 LoadEventListener.LoadType type = nullable ? 665 LoadEventListener.INTERNAL_LOAD_NULLABLE : 666 eager ? LoadEventListener.INTERNAL_LOAD_EAGER : LoadEventListener.INTERNAL_LOAD_LAZY; 667 LoadEvent event = new LoadEvent(id, entityName, true, this); 668 Object result = listeners.getLoadEventListener().onLoad(event, type); 669 if (!nullable) UnresolvableObjectException.throwIfNull(result, id, entityName); 670 return result; 671 } 672 673 public Object load(Class entityClass, Serializable id, LockMode lockMode) throws HibernateException { 674 return load( entityClass.getName(), id, lockMode ); 675 } 676 677 public Object load(String entityName, Serializable id, LockMode lockMode) throws HibernateException { 678 LoadEvent event = new LoadEvent(id, entityName, lockMode, this); 679 return listeners.getLoadEventListener().onLoad(event, LoadEventListener.LOAD); 680 } 681 682 public Object get(Class entityClass, Serializable id, LockMode lockMode) throws HibernateException { 683 return get( entityClass.getName(), id, lockMode ); 684 } 685 686 public Object get(String entityName, Serializable id, LockMode lockMode) throws HibernateException { 687 LoadEvent event = new LoadEvent(id, entityName, lockMode, this); 688 return listeners.getLoadEventListener().onLoad(event, LoadEventListener.GET); 689 } 690 691 public void refresh(Object object) throws HibernateException { 692 listeners.getRefreshEventListener().onRefresh( new RefreshEvent(object, this) ); 693 } 694 695 public void refresh(Object object, LockMode lockMode) throws HibernateException { 696 listeners.getRefreshEventListener().onRefresh( new RefreshEvent(object, lockMode, this) ); 697 } 698 699 public void refresh(Object object, Map refreshedAlready) throws HibernateException { 700 RefreshEvent refreshEvent = new RefreshEvent(object, this); 701 listeners.getRefreshEventListener().onRefresh( refreshEvent, refreshedAlready ); 702 } 703 704 public void replicate(Object obj, ReplicationMode replicationMode) throws HibernateException { 705 ReplicateEvent event = new ReplicateEvent(obj, replicationMode, this); 706 listeners.getReplicateEventListener().onReplicate(event); 707 } 708 709 public void replicate(String entityName, Object obj, ReplicationMode replicationMode) 710 throws HibernateException { 711 ReplicateEvent event = new ReplicateEvent(entityName, obj, replicationMode, this); 712 listeners.getReplicateEventListener().onReplicate(event); 713 } 714 715 |