All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.beangle.spring.hibernate.BeangleSessionContext.scala Maven / Gradle / Ivy

/*
 * Beangle, Agile Development Scaffold and Toolkit
 *
 * Copyright (c) 2005-2015, Beangle Software.
 *
 * Beangle is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Lesser General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * Beangle is distributed in the hope that it will be useful.
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public License
 * along with Beangle.  If not, see .
 */
package org.beangle.spring.hibernate

import org.beangle.spring.hibernate.internal.SessionHolder
import org.beangle.spring.hibernate.internal.SessionUtils
import org.hibernate.FlushMode
import org.hibernate.Session
import org.hibernate.SessionFactory
import org.hibernate.context.spi.CurrentSessionContext
import org.hibernate.engine.spi.SessionFactoryImplementor
import org.springframework.core.Ordered
import org.springframework.transaction.support.TransactionSynchronization
import org.springframework.transaction.support.TransactionSynchronizationManager
/**
 * @author chaostone
 */
class BeangleSessionContext(val sessionFactory: SessionFactoryImplementor) extends CurrentSessionContext {

  /**
   * Retrieve the Spring-managed Session for the current thread, if any.
   */
  def currentSession: Session = {
    val sessionHolder = SessionUtils.currentSession(this.sessionFactory)
    val session = sessionHolder.session
    // TODO what time enter into the code?
    if (TransactionSynchronizationManager.isSynchronizationActive()
      && !sessionHolder.isSynchronizedWithTransaction()) {
      TransactionSynchronizationManager.registerSynchronization(new SessionSynchronization(sessionHolder,
        this.sessionFactory))
      sessionHolder.setSynchronizedWithTransaction(true)
      // Switch to FlushMode.AUTO, as we have to assume a thread-bound Session
      // with FlushMode.MANUAL, which needs to allow flushing within the transaction.
      val flushMode = session.getFlushMode()
      if (FlushMode.MANUAL == flushMode && !TransactionSynchronizationManager.isCurrentTransactionReadOnly) {
        session.setFlushMode(FlushMode.AUTO)
        sessionHolder.previousFlushMode = flushMode
      }
    }
    session
  }
}

/**
 * Borrow from Spring Session Synchronization
 *
 * @author chaostone
 */
class SessionSynchronization(val sessionHolder: SessionHolder, val sessionFactory: SessionFactory) extends TransactionSynchronization with Ordered {

  var holderActive = true

  private def currentSession: Session = this.sessionHolder.session

  def getOrder(): Int = 1000 - 100

  def suspend() {
    if (this.holderActive) {
      TransactionSynchronizationManager.unbindResource(this.sessionFactory)
      // Eagerly disconnect the Session here, to make release mode "on_close" work on JBoss.
      currentSession.disconnect()
    }
  }

  def resume() {
    if (this.holderActive) TransactionSynchronizationManager.bindResource(this.sessionFactory, this.sessionHolder)
  }

  def flush() {
    currentSession.flush()
  }

  def beforeCommit(readOnly: Boolean) {
    if (!readOnly) {
      val session = currentSession
      // Read-write transaction -> flush the Hibernate Session.
      // Further check: only flush when not FlushMode.MANUAL.
      if (FlushMode.MANUAL != session.getFlushMode) session.flush()
    }
  }

  def beforeCompletion() {
    val session = this.sessionHolder.session
    if (this.sessionHolder.previousFlushMode != null) {
      // In case of pre-bound Session, restore previous flush mode.
      session.setFlushMode(this.sessionHolder.previousFlushMode)
    }
    // Eagerly disconnect the Session here, to make release mode "on_close" work nicely.
    session.disconnect()
  }

  def afterCommit() {
  }

  def afterCompletion(status: Int) {
    try {
      if (status != TransactionSynchronization.STATUS_COMMITTED) {
        // Clear all pending inserts/updates/deletes in the Session.
        // Necessary for pre-bound Sessions, to avoid inconsistent state.
        this.sessionHolder.session.clear()
      }
    } finally {
      this.sessionHolder.setSynchronizedWithTransaction(false)
    }
  }

}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy