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

org.scalaquery.session.Session.scala Maven / Gradle / Ivy

package org.scalaquery.session

import java.sql.{PreparedStatement, Connection, ResultSet, DatabaseMetaData, Statement}
import org.scalaquery.SQueryException

/**
 * A database session which opens a connection and transaction on demand.
 */
trait Session extends java.io.Closeable { self =>

  def conn: Connection
  def metaData: DatabaseMetaData
  def capabilities: DatabaseCapabilities

  def resultSetType: ResultSetType = ResultSetType.Auto
  def resultSetConcurrency: ResultSetConcurrency = ResultSetConcurrency.Auto
  def resultSetHoldability: ResultSetHoldability = ResultSetHoldability.Auto

  final def prepareStatement(sql: String,
             defaultType: ResultSetType = ResultSetType.ForwardOnly,
             defaultConcurrency: ResultSetConcurrency = ResultSetConcurrency.ReadOnly,
             defaultHoldability: ResultSetHoldability = ResultSetHoldability.Default): PreparedStatement = {
    resultSetHoldability.withDefault(defaultHoldability) match {
      case ResultSetHoldability.Default =>
        conn.prepareStatement(sql, resultSetType.withDefault(defaultType).intValue,
          resultSetConcurrency.withDefault(defaultConcurrency).intValue)
      case h =>
        conn.prepareStatement(sql, resultSetType.withDefault(defaultType).intValue,
          resultSetConcurrency.withDefault(defaultConcurrency).intValue,
          h.intValue)
    }
  }

  final def createStatement(defaultType: ResultSetType = ResultSetType.ForwardOnly,
             defaultConcurrency: ResultSetConcurrency = ResultSetConcurrency.ReadOnly,
             defaultHoldability: ResultSetHoldability = ResultSetHoldability.Default): Statement = {
    resultSetHoldability.withDefault(defaultHoldability) match {
      case ResultSetHoldability.Default =>
        conn.createStatement(resultSetType.withDefault(defaultType).intValue,
          resultSetConcurrency.withDefault(defaultConcurrency).intValue)
      case h =>
        conn.createStatement(resultSetType.withDefault(defaultType).intValue,
          resultSetConcurrency.withDefault(defaultConcurrency).intValue,
          h.intValue)
    }
  }

  final def withPreparedStatement[T](sql: String,
              defaultType: ResultSetType = ResultSetType.ForwardOnly,
              defaultConcurrency: ResultSetConcurrency = ResultSetConcurrency.ReadOnly,
              defaultHoldability: ResultSetHoldability = ResultSetHoldability.Default)(f: (PreparedStatement => T)): T = {
    val st = prepareStatement(sql, defaultType, defaultConcurrency, defaultHoldability)
    try f(st) finally st.close()
  }

  final def withStatement[T](defaultType: ResultSetType = ResultSetType.ForwardOnly,
              defaultConcurrency: ResultSetConcurrency = ResultSetConcurrency.ReadOnly,
              defaultHoldability: ResultSetHoldability = ResultSetHoldability.Default)(f: (Statement => T)): T = {
    val st = createStatement(defaultType, defaultConcurrency, defaultHoldability)
    try f(st) finally st.close()
  }

  def close(): Unit

  /**
   * Call this method within a withTransaction call to roll back the current
   * transaction after withTransaction returns.
   */
  def rollback(): Unit

  /**
   * Run the supplied function within a transaction. If the function throws an Exception
   * or the session's rollback() method is called, the transaction is rolled back,
   * otherwise it is commited when the function returns.
   */
  def withTransaction[T](f: => T): T

  def forParameters(rsType: ResultSetType = resultSetType, rsConcurrency: ResultSetConcurrency = resultSetConcurrency,
                    rsHoldability: ResultSetHoldability = resultSetHoldability): Session = new Session {
    override def resultSetType = rsType
    override def resultSetConcurrency = rsConcurrency
    override def resultSetHoldability = rsHoldability
    def conn = self.conn
    def metaData = self.metaData
    def capabilities = self.capabilities
    def close() = self.close()
    def rollback() = self.rollback()
    def withTransaction[T](f: => T) = self.withTransaction(f)
  }
}

class BaseSession private[session] (db: Database) extends Session {

  var open = false
  var doRollback = false
  var inTransaction = false

  lazy val conn = { open = true; db.createConnection() }
  lazy val metaData = conn.getMetaData()

  def capabilities = {
    val dc = db.capabilities
    if(dc ne null) dc
    else {
      val newDC = new DatabaseCapabilities(this)
      db.capabilities = newDC
      newDC
    }
  }

  def close() {
    if(open) conn.close()
  }

  def rollback() {
    if(conn.getAutoCommit) throw new SQueryException("Cannot roll back session in auto-commit mode")
    doRollback = true
  }

  def withTransaction[T](f: => T): T = if(inTransaction) f else {
    conn.setAutoCommit(false)
    inTransaction = true
    try {
      var done = false
      try {
        doRollback = false
        val res = f
        if(doRollback) conn.rollback()
        else conn.commit()
        done = true
        res
      } finally if(!done) conn.rollback()
    } finally {
      conn.setAutoCommit(true)
      inTransaction = false
    }
  }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy