1 16 17 package org.springframework.orm.hibernate3; 18 19 import java.util.HashMap ; 20 import java.util.Iterator ; 21 import java.util.Map ; 22 import java.util.Set ; 23 24 import javax.sql.DataSource ; 25 import javax.transaction.Status ; 26 import javax.transaction.Transaction ; 27 import javax.transaction.TransactionManager ; 28 29 import org.apache.commons.logging.Log; 30 import org.apache.commons.logging.LogFactory; 31 import org.hibernate.Criteria; 32 import org.hibernate.FlushMode; 33 import org.hibernate.HibernateException; 34 import org.hibernate.Interceptor; 35 import org.hibernate.JDBCException; 36 import org.hibernate.NonUniqueResultException; 37 import org.hibernate.ObjectDeletedException; 38 import org.hibernate.PersistentObjectException; 39 import org.hibernate.PropertyValueException; 40 import org.hibernate.Query; 41 import org.hibernate.QueryException; 42 import org.hibernate.Session; 43 import org.hibernate.SessionFactory; 44 import org.hibernate.StaleObjectStateException; 45 import org.hibernate.StaleStateException; 46 import org.hibernate.TransientObjectException; 47 import org.hibernate.UnresolvableObjectException; 48 import org.hibernate.WrongClassException; 49 import org.hibernate.connection.ConnectionProvider; 50 import org.hibernate.engine.SessionFactoryImplementor; 51 import org.hibernate.exception.ConstraintViolationException; 52 import org.hibernate.exception.DataException; 53 import org.hibernate.exception.JDBCConnectionException; 54 import org.hibernate.exception.LockAcquisitionException; 55 import org.hibernate.exception.SQLGrammarException; 56 57 import org.springframework.core.CollectionFactory; 58 import org.springframework.dao.CannotAcquireLockException; 59 import org.springframework.dao.DataAccessException; 60 import org.springframework.dao.DataAccessResourceFailureException; 61 import org.springframework.dao.DataIntegrityViolationException; 62 import org.springframework.dao.IncorrectResultSizeDataAccessException; 63 import org.springframework.dao.InvalidDataAccessApiUsageException; 64 import org.springframework.dao.InvalidDataAccessResourceUsageException; 65 import org.springframework.jdbc.datasource.DataSourceUtils; 66 import org.springframework.jdbc.support.SQLErrorCodeSQLExceptionTranslator; 67 import org.springframework.jdbc.support.SQLExceptionTranslator; 68 import org.springframework.jdbc.support.SQLStateSQLExceptionTranslator; 69 import org.springframework.transaction.jta.SpringJtaSynchronizationAdapter; 70 import org.springframework.transaction.support.TransactionSynchronizationManager; 71 import org.springframework.util.Assert; 72 73 97 public abstract class SessionFactoryUtils { 98 99 105 public static final int SESSION_SYNCHRONIZATION_ORDER = 106 DataSourceUtils.CONNECTION_SYNCHRONIZATION_ORDER - 100; 107 108 static final Log logger = LogFactory.getLog(SessionFactoryUtils.class); 109 110 private static final ThreadLocal deferredCloseHolder = new ThreadLocal (); 111 112 113 120 public static DataSource getDataSource(SessionFactory sessionFactory) { 121 if (sessionFactory instanceof SessionFactoryImplementor) { 122 ConnectionProvider cp = ((SessionFactoryImplementor) sessionFactory).getConnectionProvider(); 123 if (cp instanceof LocalDataSourceConnectionProvider) { 124 return ((LocalDataSourceConnectionProvider) cp).getDataSource(); 125 } 126 } 127 return null; 128 } 129 130 140 public static SQLExceptionTranslator newJdbcExceptionTranslator(SessionFactory sessionFactory) { 141 DataSource ds = getDataSource(sessionFactory); 142 if (ds != null) { 143 return new SQLErrorCodeSQLExceptionTranslator(ds); 144 } 145 return new SQLStateSQLExceptionTranslator(); 146 } 147 148 161 public static TransactionManager getJtaTransactionManager(SessionFactory sessionFactory, Session session) { 162 SessionFactoryImplementor sessionFactoryImpl = null; 163 if (sessionFactory instanceof SessionFactoryImplementor) { 164 sessionFactoryImpl = ((SessionFactoryImplementor) sessionFactory); 165 } 166 else if (session != null) { 167 SessionFactory internalFactory = session.getSessionFactory(); 168 if (internalFactory instanceof SessionFactoryImplementor) { 169 sessionFactoryImpl = (SessionFactoryImplementor) internalFactory; 170 } 171 } 172 return (sessionFactoryImpl != null ? sessionFactoryImpl.getTransactionManager() : null); 173 } 174 175 176 196 public static Session getSession(SessionFactory sessionFactory, boolean allowCreate) 197 throws DataAccessResourceFailureException, IllegalStateException { 198 199 try { 200 return doGetSession(sessionFactory, null, null, allowCreate); 201 } 202 catch (HibernateException ex) { 203 throw new DataAccessResourceFailureException("Could not open Hibernate Session", ex); 204 } 205 } 206 207 228 public static Session getSession( 229 SessionFactory sessionFactory, Interceptor entityInterceptor, 230 SQLExceptionTranslator jdbcExceptionTranslator) throws DataAccessResourceFailureException { 231 232 try { 233 return doGetSession(sessionFactory, entityInterceptor, jdbcExceptionTranslator, true); 234 } 235 catch (HibernateException ex) { 236 throw new DataAccessResourceFailureException("Could not open Hibernate Session", ex); 237 } 238 } 239 240 253 public static Session doGetSession(SessionFactory sessionFactory, boolean allowCreate) 254 throws HibernateException, IllegalStateException { 255 256 return doGetSession(sessionFactory, null, null, allowCreate); 257 } 258 259 276 private static Session doGetSession( 277 SessionFactory sessionFactory, Interceptor entityInterceptor, 278 SQLExceptionTranslator jdbcExceptionTranslator, boolean allowCreate) 279 throws HibernateException, IllegalStateException { 280 281 Assert.notNull(sessionFactory, "No SessionFactory specified"); 282 283 SessionHolder sessionHolder = (SessionHolder) TransactionSynchronizationManager.getResource(sessionFactory); 284 if (sessionHolder != null && !sessionHolder.isEmpty()) { 285 Session session = null; 287 if (TransactionSynchronizationManager.isSynchronizationActive() && 288 sessionHolder.doesNotHoldNonDefaultSession()) { 289 session = sessionHolder.getValidatedSession(); 292 if (session != null && !sessionHolder.isSynchronizedWithTransaction()) { 293 logger.debug("Registering Spring transaction synchronization for existing Hibernate Session"); 294 TransactionSynchronizationManager.registerSynchronization( 295 new SpringSessionSynchronization(sessionHolder, sessionFactory, jdbcExceptionTranslator, false)); 296 sessionHolder.setSynchronizedWithTransaction(true); 297 FlushMode flushMode = session.getFlushMode(); 300 if (flushMode.lessThan(FlushMode.COMMIT) && 301 !TransactionSynchronizationManager.isCurrentTransactionReadOnly()) { 302 session.setFlushMode(FlushMode.AUTO); 303 sessionHolder.setPreviousFlushMode(flushMode); 304 } 305 } 306 } 307 else { 308 session = getJtaSynchronizedSession(sessionHolder, sessionFactory, jdbcExceptionTranslator); 310 } 311 if (session != null) { 312 return session; 313 } 314 } 315 316 logger.debug("Opening Hibernate Session"); 317 Session session = (entityInterceptor != null ? 318 sessionFactory.openSession(entityInterceptor) : sessionFactory.openSession()); 319 320 if (TransactionSynchronizationManager.isSynchronizationActive()) { 323 logger.debug("Registering Spring transaction synchronization for new Hibernate Session"); 325 SessionHolder holderToUse = sessionHolder; 326 if (holderToUse == null) { 327 holderToUse = new SessionHolder(session); 328 } 329 else { 330 holderToUse.addSession(session); 331 } 332 if (TransactionSynchronizationManager.isCurrentTransactionReadOnly()) { 333 session.setFlushMode(FlushMode.NEVER); 334 } 335 TransactionSynchronizationManager.registerSynchronization( 336 new SpringSessionSynchronization(holderToUse, sessionFactory, jdbcExceptionTranslator, true)); 337 holderToUse.setSynchronizedWithTransaction(true); 338 if (holderToUse != sessionHolder) { 339 TransactionSynchronizationManager.bindResource(sessionFactory, holderToUse); 340 } 341 } 342 else { 343 registerJtaSynchronization(session, sessionFactory, jdbcExceptionTranslator, sessionHolder); 345 } 346 347 if (!allowCreate && !isSessionTransactional(session, sessionFactory)) { 349 closeSession(session); 350 throw new IllegalStateException ("No Hibernate Session bound to thread, " + 351 "and configuration does not allow creation of non-transactional one here"); 352 } 353 354 return session; 355 } 356 357 367 private static Session getJtaSynchronizedSession( 368 SessionHolder sessionHolder, SessionFactory sessionFactory, 369 SQLExceptionTranslator jdbcExceptionTranslator) throws DataAccessResourceFailureException { 370 371 TransactionManager jtaTm = getJtaTransactionManager(sessionFactory, sessionHolder.getAnySession()); 375 if (jtaTm != null) { 376 try { 381 Transaction jtaTx = jtaTm.getTransaction(); 383 if (jtaTx != null) { 384 int jtaStatus = jtaTx.getStatus(); 385 if (jtaStatus == Status.STATUS_ACTIVE || jtaStatus == Status.STATUS_MARKED_ROLLBACK) { 386 Session session = sessionHolder.getValidatedSession(jtaTx); 387 if (session == null && !sessionHolder.isSynchronizedWithTransaction()) { 388 session = sessionHolder.getValidatedSession(); 394 if (session != null) { 395 logger.debug("Registering JTA transaction synchronization for existing Hibernate Session"); 396 sessionHolder.addSession(jtaTx, session); 397 jtaTx.registerSynchronization( 398 new SpringJtaSynchronizationAdapter( 399 new SpringSessionSynchronization(sessionHolder, sessionFactory, jdbcExceptionTranslator, false), 400 jtaTm)); 401 sessionHolder.setSynchronizedWithTransaction(true); 402 FlushMode flushMode = session.getFlushMode(); 405 if (flushMode.lessThan(FlushMode.COMMIT)) { 406 session.setFlushMode(FlushMode.AUTO); 407 sessionHolder.setPreviousFlushMode(flushMode); 408 } 409 } 410 } 411 return session; 412 } 413 } 414 return sessionHolder.getValidatedSession(); 417 } 418 catch (Throwable ex) { 419 throw new DataAccessResourceFailureException("Could not check JTA transaction", ex); 420 } 421 } 422 else { 423 return sessionHolder.getValidatedSession(); 426 } 427 } 428 429 437 private static void registerJtaSynchronization(Session session, SessionFactory sessionFactory, 438 SQLExceptionTranslator jdbcExceptionTranslator, SessionHolder sessionHolder) { 439 440 TransactionManager jtaTm = getJtaTransactionManager(sessionFactory, session); 444 if (jtaTm != null) { 445 try { 446 Transaction jtaTx = jtaTm.getTransaction(); 447 if (jtaTx != null) { 448 int jtaStatus = jtaTx.getStatus(); 449 if (jtaStatus == Status.STATUS_ACTIVE || jtaStatus == Status.STATUS_MARKED_ROLLBACK) { 450 logger.debug("Registering JTA transaction synchronization for new Hibernate Session"); 451 SessionHolder holderToUse = sessionHolder; 452 if (holderToUse == null) { 455 holderToUse = new SessionHolder(jtaTx, session); 456 } 457 else { 458 holderToUse.addSession(jtaTx, session); 459 } 460 jtaTx.registerSynchronization( 461 new SpringJtaSynchronizationAdapter( 462 new SpringSessionSynchronization(holderToUse, sessionFactory, jdbcExceptionTranslator, true), 463 jtaTm)); 464 holderToUse.setSynchronizedWithTransaction(true); 465 if (holderToUse != sessionHolder) { 466 TransactionSynchronizationManager.bindResource(sessionFactory, holderToUse); 467 } 468 } 469 } 470 } 471 catch (Throwable ex) { 472 throw new DataAccessResourceFailureException( 473 "Could not register synchronization with JTA TransactionManager", ex); 474 } 475 } 476 } 477 478 479 489 public static Session getNewSession(SessionFactory sessionFactory) { 490 return getNewSession(sessionFactory, null); 491 } 492 493 504 public static Session getNewSession(SessionFactory sessionFactory, Interceptor entityInterceptor) { 505 Assert.notNull(sessionFactory, "No SessionFactory specified"); 506 507 try { 508 SessionHolder sessionHolder = (SessionHolder) TransactionSynchronizationManager.getResource(sessionFactory); 509 if (sessionHolder != null && !sessionHolder.isEmpty()) { 510 if (entityInterceptor != null) { 511 return sessionFactory.openSession(sessionHolder.getAnySession().connection(), entityInterceptor); 512 } 513 else { 514 return sessionFactory.openSession(sessionHolder.getAnySession().connection()); 515 } 516 } 517 else { 518 if (entityInterceptor != null) { 519 return sessionFactory.openSession(entityInterceptor); 520 } 521 else { 522 return sessionFactory.openSession(); 523 } 524 } 525 } 526 catch (HibernateException ex) { 527 throw new DataAccessResourceFailureException("Could not open Hibernate Session", ex); 528 } 529 } 530 531 532 544 public static String toString(Session session) { 545 return session.getClass().getName() + "@" + Integer.toHexString(System.identityHashCode(session)); 546 } 547 548 556 public static boolean isSessionTransactional(Session session, SessionFactory sessionFactory) { 557 if (sessionFactory == null) { 558 return false; 559 } 560 SessionHolder sessionHolder = 561 (SessionHolder) TransactionSynchronizationManager.getResource(sessionFactory); 562 return (sessionHolder != null && sessionHolder.containsSession(session)); 563 } 564 565 573 public static void applyTransactionTimeout(Query query, SessionFactory sessionFactory) { 574 Assert.notNull(query, "No Query object specified"); 575 if (sessionFactory != null) { 576 SessionHolder sessionHolder = 577 (SessionHolder) TransactionSynchronizationManager.getResource(sessionFactory); 578 if (sessionHolder != null && sessionHolder.hasTimeout()) { 579 query.setTimeout(sessionHolder.getTimeToLiveInSeconds()); 580 } 581 } 582 } 583 584 591 public static void applyTransactionTimeout(Criteria criteria, SessionFactory sessionFactory) { 592 Assert.notNull(criteria, "No Criteria object specified"); 593 SessionHolder sessionHolder = 594 (SessionHolder) TransactionSynchronizationManager.getResource(sessionFactory); 595 if (sessionHolder != null && sessionHolder.hasTimeout()) { 596 criteria.setTimeout(sessionHolder.getTimeToLiveInSeconds()); 597 } 598 } 599 600 608 public static DataAccessException convertHibernateAccessException(HibernateException ex) { 609 if (ex instanceof JDBCConnectionException) { 610 return new DataAccessResourceFailureException(ex.getMessage(), ex); 611 } 612 if (ex instanceof SQLGrammarException) { 613 return new InvalidDataAccessResourceUsageException(ex.getMessage(), ex); 614 } 615 if (ex instanceof DataException) { 616 return new InvalidDataAccessResourceUsageException(ex.getMessage(), ex); 617 } 618 if (ex instanceof LockAcquisitionException) { 619 return new CannotAcquireLockException(ex.getMessage(), ex); 620 } 621 if (ex instanceof ConstraintViolationException) { 622 return new DataIntegrityViolationException(ex.getMessage(), ex); 623 } 624 if (ex instanceof JDBCException) { 625 return new HibernateJdbcException((JDBCException) ex); 626 } 627 if (ex instanceof PropertyValueException) { 628 return new DataIntegrityViolationException(ex.getMessage(), ex); 629 } 630 if (ex instanceof PersistentObjectException) { 631 return new InvalidDataAccessApiUsageException(ex.getMessage(), ex); 632 } 633 if (ex instanceof TransientObjectException) { 634 return new InvalidDataAccessApiUsageException(ex.getMessage(), ex); 635 } 636 if (ex instanceof ObjectDeletedException) { 637 return new InvalidDataAccessApiUsageException(ex.getMessage(), ex); 638 } 639 if (ex instanceof QueryException) { 640 return new HibernateQueryException((QueryException) ex); 641 } 642 if (ex instanceof UnresolvableObjectException) { 643 return new HibernateObjectRetrievalFailureException((UnresolvableObjectException) ex); 644 } 645 if (ex instanceof WrongClassException) { 646 return new HibernateObjectRetrievalFailureException((WrongClassException) ex); 647 } 648 if (ex instanceof NonUniqueResultException) { 649 return new IncorrectResultSizeDataAccessException(ex.getMessage(), 1); 650 } 651 if (ex instanceof StaleObjectStateException) { 652 return new HibernateOptimisticLockingFailureException((StaleObjectStateException) ex); 653 } 654 if (ex instanceof StaleStateException) { 655 return new HibernateOptimisticLockingFailureException((StaleStateException) ex); 656 } 657 658 return new HibernateSystemException(ex); 660 } 661 662 663 669 public static boolean isDeferredCloseActive(SessionFactory sessionFactory) { 670 Assert.notNull(sessionFactory, "No SessionFactory specified"); 671 Map holderMap = (Map ) deferredCloseHolder.get(); 672 return (holderMap != null && holderMap.containsKey(sessionFactory)); 673 } 674 675 688 public static void initDeferredClose(SessionFactory sessionFactory) { 689 Assert.notNull(sessionFactory, "No SessionFactory specified"); 690 logger.debug("Initializing deferred close of Hibernate Sessions"); 691 Map holderMap = (Map ) deferredCloseHolder.get(); 692 if (holderMap == null) { 693 holderMap = new HashMap (); 694 deferredCloseHolder.set(holderMap); 695 } 696 holderMap.put(sessionFactory, CollectionFactory.createLinkedSetIfPossible(4)); 697 } 698 699 706 public static void processDeferredClose(SessionFactory sessionFactory) { 707 Assert.notNull(sessionFactory, "No SessionFactory specified"); 708 709 Map holderMap = (Map ) deferredCloseHolder.get(); 710 if (holderMap == null || !holderMap.containsKey(sessionFactory)) { 711 throw new IllegalStateException ("Deferred close not active for SessionFactory [" + sessionFactory + "]"); 712 } 713 714 logger.debug("Processing deferred close of Hibernate Sessions"); 715 Set sessions = (Set ) holderMap.remove(sessionFactory); 716 for (Iterator it = sessions.iterator(); it.hasNext();) { 717 closeSession((Session) it.next()); 718 } 719 720 if (holderMap.isEmpty()) { 721 deferredCloseHolder.set(null); 722 } 723 } 724 725 732 public static void releaseSession(Session session, SessionFactory sessionFactory) { 733 if (session == null) { 734 return; 735 } 736 if (!isSessionTransactional(session, sessionFactory)) { 738 closeSessionOrRegisterDeferredClose(session, sessionFactory); 739 } 740 } 741 742 750 static void closeSessionOrRegisterDeferredClose(Session session, SessionFactory sessionFactory) { 751 Map holderMap = (Map ) deferredCloseHolder.get(); 752 if (holderMap != null && sessionFactory != null && holderMap.containsKey(sessionFactory)) { 753 logger.debug("Registering Hibernate Session for deferred close"); 754 session.setFlushMode(FlushMode.NEVER); 756 Set sessions = (Set ) holderMap.get(sessionFactory); 757 sessions.add(session); 758 } 759 else { 760 closeSession(session); 761 } 762 } 763 764 770 public static void closeSession(Session session) { 771 if (session != null) { 772 logger.debug("Closing Hibernate Session"); 773 try { 774 session.close(); 775 } 776 catch (HibernateException ex) { 777 logger.debug("Could not close Hibernate Session", ex); 778 } 779 catch (Throwable ex) { 780 logger.debug("Unexpected exception on closing Hibernate Session", ex); 781 } 782 } 783 } 784 785 } 786 | Popular Tags |