📄 sessionfactoryutils.java
字号:
// Use same Session for further Hibernate actions within the transaction.
// Thread object will get removed by synchronization at transaction completion.
if (TransactionSynchronizationManager.isSynchronizationActive()) {
// We're within a Spring-managed transaction, possibly from JtaTransactionManager.
logger.debug("Registering Spring transaction synchronization for new Hibernate session");
sessionHolder = new SessionHolder(session);
TransactionSynchronizationManager.registerSynchronization(
new SpringSessionSynchronization(sessionHolder, sessionFactory, jdbcExceptionTranslator, true));
sessionHolder.setSynchronizedWithTransaction(true);
TransactionSynchronizationManager.bindResource(sessionFactory, sessionHolder);
}
else {
// No Spring transaction management active -> try JTA transaction synchronization.
registerJtaSynchronization(session, sessionFactory, jdbcExceptionTranslator, sessionHolder);
}
}
return session;
}
catch (JDBCException ex) {
// SQLException underneath
throw new DataAccessResourceFailureException("Could not open Hibernate session", ex.getSQLException());
}
catch (HibernateException ex) {
throw new DataAccessResourceFailureException("Could not open Hibernate session", ex);
}
}
/**
* Retrieve a Session from the given SessionHolder, potentially from a
* JTA transaction synchronization.
* @param sessionHolder the SessionHolder to check
* @param sessionFactory the SessionFactory to get the JTA TransactionManager from
* @return the associated Session, if any
*/
private static Session getJtaSynchronizedSession(
SessionHolder sessionHolder, SessionFactory sessionFactory,
SQLExceptionTranslator jdbcExceptionTranslator, boolean allowSynchronization) {
// JTA synchronization is only possible with a javax.transaction.TransactionManager.
// We'll check the Hibernate SessionFactory: If a TransactionManagerLookup is specified
// in Hibernate configuration, it will contain a TransactionManager reference.
TransactionManager jtaTm = getJtaTransactionManager(sessionFactory, sessionHolder.getAnySession());
if (jtaTm != null) {
// Check whether JTA transaction management is active ->
// fetch pre-bound Session for the current JTA transaction, if any.
// (just necessary for JTA transaction suspension, with an individual
// Hibernate Session per currently active/suspended transaction)
try {
int jtaStatus = jtaTm.getStatus();
if (jtaStatus == Status.STATUS_ACTIVE || jtaStatus == Status.STATUS_MARKED_ROLLBACK) {
// look for transaction-specific Session
Transaction jtaTx = jtaTm.getTransaction();
Session session = sessionHolder.getSession(jtaTx);
if (session == null && allowSynchronization && !sessionHolder.isSynchronizedWithTransaction()) {
// No transaction-specific Session found: If not already marked as
// synchronized with transaction, register the default thread-bound
// Session as JTA-transactional. If there is no default Session,
// we're a new inner JTA transaction with an outer one being suspended:
// In that case, we'll return null to trigger opening of a new Session.
session = sessionHolder.getSession();
if (session != null) {
logger.debug("Registering JTA transaction synchronization for existing Hibernate session");
sessionHolder.addSession(jtaTx, session);
jtaTx.registerSynchronization(
new JtaSessionSynchronization(
new SpringSessionSynchronization(
sessionHolder, sessionFactory, jdbcExceptionTranslator, false),
jtaTm));
sessionHolder.setSynchronizedWithTransaction(true);
// Switch to FlushMode.AUTO, as we have to assume a thread-bound Session
// with FlushMode.NEVER, which needs to allow flushing within the transaction.
FlushMode flushMode = sessionHolder.getSession().getFlushMode();
if (FlushMode.NEVER.equals(flushMode)) {
sessionHolder.getSession().setFlushMode(FlushMode.AUTO);
sessionHolder.setPreviousFlushMode(flushMode);
}
}
}
return session;
}
else {
// No transaction active -> simply return default thread-bound Session, if any
// (possibly from OpenSessionInViewFilter/Interceptor).
return sessionHolder.getSession();
}
}
catch (Exception ex) {
throw new DataAccessResourceFailureException("Could not check JTA transaction", ex);
}
}
else {
// No JTA TransactionManager -> simply return default thread-bound Session, if any
// (possibly from OpenSessionInViewFilter/Interceptor).
return sessionHolder.getSession();
}
}
/**
* Register a JTA synchronization for the given Session, if any.
* @param sessionHolder the existing thread-bound SessionHolder, if any
* @param session the Session to register
* @param sessionFactory the SessionFactory that the Session was created with
* @param jdbcExceptionTranslator SQLExcepionTranslator to use for flushing the
* Session on transaction synchronization (can be null)
*/
private static void registerJtaSynchronization(Session session, SessionFactory sessionFactory,
SQLExceptionTranslator jdbcExceptionTranslator, SessionHolder sessionHolder) {
// JTA synchronization is only possible with a javax.transaction.TransactionManager.
// We'll check the Hibernate SessionFactory: If a TransactionManagerLookup is specified
// in Hibernate configuration, it will contain a TransactionManager reference.
TransactionManager jtaTm = getJtaTransactionManager(sessionFactory, session);
if (jtaTm != null) {
try {
int jtaStatus = jtaTm.getStatus();
if (jtaStatus == Status.STATUS_ACTIVE || jtaStatus == Status.STATUS_MARKED_ROLLBACK) {
logger.debug("Registering JTA transaction synchronization for new Hibernate session");
javax.transaction.Transaction jtaTx = jtaTm.getTransaction();
SessionHolder holderToUse = sessionHolder;
// Register JTA Transaction with existing SessionHolder.
// Create a new SessionHolder if none existed before.
if (holderToUse == null) {
holderToUse = new SessionHolder(jtaTx, session);
}
else {
holderToUse.addSession(jtaTx, session);
}
jtaTx.registerSynchronization(
new JtaSessionSynchronization(
new SpringSessionSynchronization(
holderToUse, sessionFactory, jdbcExceptionTranslator, true),
jtaTm));
holderToUse.setSynchronizedWithTransaction(true);
if (holderToUse != sessionHolder) {
TransactionSynchronizationManager.bindResource(sessionFactory, holderToUse);
}
}
}
catch (Exception ex) {
throw new DataAccessResourceFailureException(
"Could not register synchronization with JTA TransactionManager", ex);
}
}
}
/**
* Get a new Hibernate Session from the given SessionFactory.
* Will return a new Session even if there already is a pre-bound
* Session for the given SessionFactory.
* <p>Within a transaction, this method will create a new Session
* that shares the transaction's JDBC Connection. More specifically,
* it will use the same JDBC Connection as the pre-bound Hibernate Session.
* @param sessionFactory Hibernate SessionFactory to create the session with
* @return the new Session
*/
public static Session getNewSession(SessionFactory sessionFactory) {
return getNewSession(sessionFactory, null);
}
/**
* Get a new Hibernate Session from the given SessionFactory.
* Will return a new Session even if there already is a pre-bound
* Session for the given SessionFactory.
* <p>Within a transaction, this method will create a new Session
* that shares the transaction's JDBC Connection. More specifically,
* it will use the same JDBC Connection as the pre-bound Hibernate Session.
* @param sessionFactory Hibernate SessionFactory to create the session with
* @param entityInterceptor Hibernate entity interceptor, or null if none
* @return the new Session
*/
public static Session getNewSession(SessionFactory sessionFactory, Interceptor entityInterceptor) {
Assert.notNull(sessionFactory, "No SessionFactory specified");
try {
SessionHolder sessionHolder = (SessionHolder) TransactionSynchronizationManager.getResource(sessionFactory);
if (sessionHolder != null && !sessionHolder.isEmpty()) {
if (entityInterceptor != null) {
return sessionFactory.openSession(sessionHolder.getAnySession().connection(), entityInterceptor);
}
else {
return sessionFactory.openSession(sessionHolder.getAnySession().connection());
}
}
else {
if (entityInterceptor != null) {
return sessionFactory.openSession(entityInterceptor);
}
else {
return sessionFactory.openSession();
}
}
}
catch (JDBCException ex) {
// SQLException underneath
throw new DataAccessResourceFailureException("Could not open Hibernate session", ex.getSQLException());
}
catch (HibernateException ex) {
throw new DataAccessResourceFailureException("Could not open Hibernate session", ex);
}
}
/**
* Return whether the given Hibernate Session is transactional, that is,
* bound to the current thread by Spring's transaction facilities.
* @param session the Hibernate Session to check
* @param sessionFactory Hibernate SessionFactory that the Session was created with
* @return whether the Session is transactional
*/
public static boolean isSessionTransactional(Session session, SessionFactory sessionFactory) {
SessionHolder sessionHolder =
(SessionHolder) TransactionSynchronizationManager.getResource(sessionFactory);
return (sessionHolder != null && sessionHolder.containsSession(session));
}
/**
* Apply the current transaction timeout, if any, to the given
* Hibernate Query object.
* @param query the Hibernate Query object
* @param sessionFactory Hibernate SessionFactory that the Query was created for
* @see net.sf.hibernate.Query#setTimeout
*/
public static void applyTransactionTimeout(Query query, SessionFactory sessionFactory) {
Assert.notNull(query, "No Query object specified");
SessionHolder sessionHolder =
(SessionHolder) TransactionSynchronizationManager.getResource(sessionFactory);
if (sessionHolder != null && sessionHolder.hasTimeout()) {
query.setTimeout(sessionHolder.getTimeToLiveInSeconds());
}
}
/**
* Apply the current transaction timeout, if any, to the given
* Hibernate Criteria object.
* @param criteria the Hibernate Criteria object
* @param sessionFactory Hibernate SessionFactory that the Criteria was created for
* @see net.sf.hibernate.Criteria#setTimeout
*/
public static void applyTransactionTimeout(Criteria criteria, SessionFactory sessionFactory) {
Assert.notNull(criteria, "No Criteria object specified");
SessionHolder sessionHolder =
(SessionHolder) TransactionSynchronizationManager.getResource(sessionFactory);
if (sessionHolder != null && sessionHolder.hasTimeout()) {
criteria.setTimeout(sessionHolder.getTimeToLiveInSeconds());
}
}
/**
* Convert the given HibernateException to an appropriate exception from the
* org.springframework.dao hierarchy. Note that it is advisable to handle
* JDBCException specifically by using an SQLExceptionTranslator for the
* underlying SQLException.
* @param ex HibernateException that occured
* @return the corresponding DataAccessException instance
* @see HibernateAccessor#convertHibernateAccessException
* @see HibernateAccessor#convertJdbcAccessException
* @see HibernateTransactionManager#convertHibernateAccessException
* @see HibernateTransactionManager#convertJdbcAccessException
* @see net.sf.hibernate.JDBCException#getSQLException
* @see org.springframework.jdbc.support.SQLExceptionTranslator
*/
public static DataAccessException convertHibernateAccessException(HibernateException ex) {
if (ex instanceof JDBCException) {
// SQLException during Hibernate access: only passed in here from custom code,
// as HibernateTemplate etc will use SQLExceptionTranslator-based handling
return new HibernateJdbcException((JDBCException) ex);
}
if (ex instanceof UnresolvableObjectException) {
return new HibernateObjectRetrievalFailureException((UnresolvableObjectException) ex);
}
if (ex instanceof ObjectNotFoundException) {
return new HibernateObjectRetrievalFailureException((ObjectNotFoundException) ex);
}
if (ex instanceof ObjectDeletedException) {
return new HibernateObjectRetrievalFailureException((ObjectDeletedException) ex);
}
if (ex instanceof WrongClassException) {
return new HibernateObjectRetrievalFailureException((WrongClassException) ex);
}
if (ex instanceof StaleObjectStateException) {
return new HibernateOptimisticLockingFailureException((StaleObjectStateException) ex);
}
if (ex instanceof QueryException) {
return new HibernateQueryException((QueryException) ex);
}
if (ex instanceof PersistentObjectException) {
return new InvalidDataAccessApiUsageException(ex.getMessage());
}
if (ex instanceof TransientObjectException) {
return new InvalidDataAccessApiUsageException(ex.getMessage());
}
// fallback
return new HibernateSystemException(ex);
}
/**
* Return if deferred close is active for the current thread
* and the given SessionFactory.
* @param sessionFactory the Hibernate SessionFactory to check
*/
public static boolean isDeferredCloseActive(SessionFactory sessionFactory) {
Assert.notNull(sessionFactory, "No SessionFactory specified");
Map holderMap = (Map) deferredCloseHolder.get();
return (holderMap != null && holderMap.containsKey(sessionFactory));
}
/**
* Initialize deferred close for the current thread and the given SessionFactory.
* Sessions will not be actually closed on close calls then, but rather at a
* processDeferredClose call at a finishing point (like request completion).
* <p>Used by OpenSessionInViewFilter and OpenSessionInViewInterceptor
* when not configured for a single session.
* @param sessionFactory Hibernate SessionFactory
* @see #processDeferredClose
* @see #closeSessionIfNecessary
* @see org.springframework.orm.hibernate.support.OpenSessionInViewFilter#setSingleSession
* @see org.springframework.orm.hibernate.support.OpenSessionInViewInterceptor#setSingleSession
*/
public static void initDeferredClose(SessionFactory sessionFactory) {
Assert.notNull(sessionFactory, "No SessionFactory specified");
logger.debug("Initializing deferred close of Hibernate sessions");
Map holderMap = (Map) deferredCloseHolder.get();
if (holderMap == null) {
holderMap = new HashMap();
deferredCloseHolder.set(holderMap);
}
holderMap.put(sessionFactory, new HashSet());
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -