Many resources are needed to download a project. Please understand that we have to compensate our server costs. Thank you in advance. Project price only 1 $
You can buy this project and download/modify it how often you want.
/*
* Copyright 2011 Kazuhiro Sera
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
* either express or implied. See the License for the specific language
* governing permissions and limitations under the License.
*/
package scalikejdbc
import java.sql.Connection
import java.lang.IllegalStateException
import scala.util.control.Exception._
/**
* Basic Database Accessor
*
* You can start with DB and blocks if using [[scalikejdbc.ConnectionPool.singleton()]].
*
* Using DBSession:
*
* {{{
* ConnectionPool.singletion("jdbc:...","user","password")
* case class User(id: Int, name: String)
*
* val users = DB readOnly { session =>
* session.list("select * from user") { rs =>
* User(rs.int("id"), rs.string("name"))
* }
* }
*
* DB autoCommit { session =>
* session.update("insert into user values (?,?)", 123, "Alice")
* }
*
* DB localTx { session =>
* session.update("insert into user values (?,?)", 123, "Alice")
* }
*
* using(DB(ConnectionPool.borrow())) { db =>
* db.begin()
* try {
* DB withTx { session =>
* session.update("update user set name = ? where id = ?", "Alice", 123)
* }
* db.commit()
* } catch { case e =>
* db.rollbackIfActive()
* throw e
* }
* }
* }}}
*
* Using SQL:
*
* {{{
* ConnectionPool.singletion("jdbc:...","user","password")
* case class User(id: Int, name: String)
*
* val users = DB readOnly { session =>
* SQL("select * from user").map { rs =>
* User(rs.int("id"), rs.string("name"))
* }.list.apply()
* }
*
* DB autoCommit { session =>
* SQL("insert into user values (?,?)").bind(123, "Alice").update.apply()
* }
*
* DB localTx { session =>
* SQL("insert into user values (?,?)").bind(123, "Alice").update.apply()
* }
*
* using(DB(ConnectionPool.borrow())) { db =>
* db.begin()
* try {
* DB withTx { session =>
* SQL("update user set name = ? where id = ?").bind("Alice", 123).update.apply()
* }
* db.commit()
* } catch { case e =>
* db.rollbackIfActive()
* throw e
* }
* }
* }}}
*/
object DB {
/**
* Returns DB instance.
* @param conn connection
* @return DB instance
*/
def apply(conn: => Connection): DB = new DB(conn)
private def ensureDBInstance(db: DB): Unit = {
if (db == null) {
throw new IllegalStateException(ErrorMessage.IMPLICIT_DB_INSTANCE_REQUIRED)
}
}
/**
* Begins a read-only block easily with ConnectionPool.
*
* @param execution execution
* @tparam A return type
* @return result value
*/
def readOnly[A](execution: DBSession => A): A = {
using(ConnectionPool.borrow()) {
conn => DB(conn).readOnly(execution)
}
}
/**
* Begins a read-only block easily with ConnectionPool
* and pass not session but connection to execution block.
*
* @param execution execution
* @tparam A return type
* @return result value
*/
def readOnlyWithConnection[A](execution: Connection => A): A = {
using(ConnectionPool.borrow()) {
conn => DB(conn).readOnlyWithConnection(execution)
}
}
/**
* Returns read-only session instance. You SHOULD close this instance by yourself.
* @return session
*/
def readOnlySession(): DBSession = DB(ConnectionPool.borrow()).readOnlySession()
/**
* Begins a auto-commit block easily with ConnectionPool.
* @param execution execution
* @tparam A return type
* @return result value
*/
def autoCommit[A](execution: DBSession => A): A = {
using(ConnectionPool.borrow()) {
conn => DB(conn).autoCommit(execution)
}
}
/**
* Begins a auto-commit block easily with ConnectionPool
* and pass not session but connection to execution block.
*
* @param execution execution
* @tparam A return type
* @return result value
*/
def autoCommitWithConnection[A](execution: Connection => A): A = {
using(ConnectionPool.borrow()) {
conn => DB(conn).autoCommitWithConnection(execution)
}
}
/**
* Returns auto-commit session instance. You SHOULD close this instance by yourself.
* @return session
*/
def autoCommitSession(): DBSession = DB(ConnectionPool.borrow()).autoCommitSession()
/**
* Begins a local-tx block easily with ConnectionPool.
* @param execution execution
* @tparam A return type
* @return result value
*/
def localTx[A](execution: DBSession => A): A = {
using(ConnectionPool.borrow()) {
conn => DB(conn).localTx(execution)
}
}
/**
* Begins a local-tx block easily with ConnectionPool
* and pass not session but connection to execution block.
*
* @param execution execution
* @tparam A return type
* @return result value
*/
def localTxWithConnection[A](execution: Connection => A): A = {
using(ConnectionPool.borrow()) {
conn => DB(conn).localTxWithConnection(execution)
}
}
/**
* Begins a within-tx block easily with a DB instance as an implicit parameter.
*
* @param execution execution
* @param db DB instance as an implicit parameter
* @tparam A return type
* @return result value
*/
def withinTx[A](execution: DBSession => A)(implicit db: DB): A = {
ensureDBInstance(db: DB)
db.withinTx(execution)
}
/**
* Begins a within-tx block easily with a DB instance as an implicit parameter
* and pass not session but connection to execution block.
*
* @param execution execution
* @param db DB instance as an implicit parameter
* @tparam A return type
* @return result value
*/
def withinTxWithConnection[A](execution: Connection => A)(implicit db: DB): A = {
ensureDBInstance(db: DB)
db.withinTxWithConnection(execution)
}
/**
* Returns within-tx session instance. You SHOULD close this instance by yourself.
*
* @return session
*/
def withinTxSession(): DBSession = DB(ConnectionPool.borrow()).withinTxSession()
/**
* Get a connection and returns a DB instance.
*
* @param conn connection
* @return DB instance
*/
def connect(conn: Connection = ConnectionPool.borrow()): DB = DB(conn)
/**
* Returns a DB instance by using an implicit Connection object.
*
* @param conn connection
* @return DB instance
*/
def connected(implicit conn: Connection) = DB(conn)
}
/**
* Basic Database Accessor
*
* Using DBSession:
*
* {{{
* import scalikejdbc._
* case class User(id: Int, name: String)
*
* using(ConnectionPool.borrow()) { conn =>
*
* val users = DB(conn) readOnly { session =>
* session.list("select * from user") { rs =>
* User(rs.int("id"), rs.string("name"))
* }
* }
*
* DB(conn) autoCommit { session =>
* session.update("insert into user values (?,?)", 123, "Alice")
* }
*
* DB(conn) localTx { session =>
* session.update("insert into user values (?,?)", 123, "Alice")
* }
*
* }
* }}}
*
* Using SQL:
*
* {{{
* import scalikejdbc._
* case class User(id: Int, name: String)
*
* using(ConnectionPool.borrow()) { conn =>
*
* val users = DB(conn) readOnly { session =>
* SQL("select * from user").map { rs =>
* User(rs.int("id"), rs.string("name"))
* }.list.apply()
* }
*
* DB(conn) autoCommit { session =>
* SQL("insert into user values (?,?)").bind(123, "Alice").update.apply()
* }
*
* DB(conn) localTx { session =>
* SQL("insert into user values (?,?)").bind(123, "Alice").update.apply()
* }
*
* }
* }}}
*/
case class DB(conn: Connection) extends LogSupport {
/**
* Returns is the current transaction is active.
* @return result
*/
def isTxNotActive: Boolean = conn == null || conn.isClosed || conn.isReadOnly
/**
* Returns is the current transaction hasn't started yet.
* @return result
*/
def isTxNotYetStarted: Boolean = conn != null && conn.getAutoCommit
/**
* Returns is the current transaction already started.
* @return result
*/
def isTxAlreadyStarted: Boolean = conn != null && !conn.getAutoCommit
private def newTx(conn: Connection): Tx = {
if (isTxNotActive || isTxAlreadyStarted) {
throw new IllegalStateException(ErrorMessage.CANNOT_START_A_NEW_TRANSACTION)
}
new Tx(conn)
}
/**
* Starts a new transaction and returns it.
* @return tx
*/
def newTx: Tx = newTx(conn)
/**
* Returns the current transaction.
* If the transaction has not started yet, IllegalStateException will be thrown.
* @return tx
*/
def currentTx: Tx = {
if (isTxNotActive || isTxNotYetStarted) {
throw new IllegalStateException(ErrorMessage.TRANSACTION_IS_NOT_ACTIVE)
}
new Tx(conn)
}
/**
* Returns the current transaction.
* If the transaction has not started yet, IllegalStateException will be thrown.
* @return tx
*/
def tx: Tx = {
handling(classOf[IllegalStateException]) by {
e =>
throw new IllegalStateException(
ErrorMessage.TRANSACTION_IS_NOT_ACTIVE +
" If you want to start a new transaction, use #newTx instead."
)
} apply currentTx
}
/**
* Close the connection.
*/
def close(): Unit = {
ignoring(classOf[Throwable]) {
conn.close()
}
log.debug("A Connection is closed.")
}
/**
* Begins a new transaction.
*/
def begin(): Unit = newTx.begin()
/**
* Begins a new transaction if the other one does not already start.
*/
def beginIfNotYet(): Unit = {
ignoring(classOf[IllegalStateException]) apply {
begin()
}
}
/**
* Commits the current transaction.
*/
def commit(): Unit = tx.commit()
/**
* Rolls back the current transaction.
*/
def rollback(): Unit = tx.rollback()
/**
* Rolls back the current transaction if the transaction is still active.
*/
def rollbackIfActive(): Unit = {
ignoring(classOf[IllegalStateException]) apply {
tx.rollbackIfActive()
}
}
/**
* Returns read-only session.
* @return session
*/
def readOnlySession(): DBSession = {
conn.setReadOnly(true)
DBSession(conn, isReadOnly = true)
}
/**
* Provides read-only session block.
* @param execution block
* @tparam A return type
* @return result value
*/
def readOnly[A](execution: DBSession => A): A = {
using(conn) { conn =>
execution(readOnlySession())
}
}
/**
* Provides read-only session block.
* @param execution block
* @tparam A return type
* @return result value
*/
def readOnlyWithConnection[A](execution: Connection => A): A = {
// cannot control if jdbc drivers ignore the readOnly attribute.
using(conn) { conn =>
execution(readOnlySession().conn)
}
}
/**
* Returns auto-commit session.
* @return session
*/
def autoCommitSession(): DBSession = {
conn.setReadOnly(false)
conn.setAutoCommit(true)
DBSession(conn)
}
/**
* Provides auto-commit session block.
* @param execution block
* @tparam A return type
* @return result value
*/
def autoCommit[A](execution: DBSession => A): A = {
using(conn) { conn =>
execution(autoCommitSession())
}
}
/**
* Provides auto-commit session block.
* @param execution block
* @tparam A return type
* @return result value
*/
def autoCommitWithConnection[A](execution: Connection => A): A = {
using(conn) { conn =>
execution(autoCommitSession().conn)
}
}
/**
* Returns within-tx session.
* @return session
*/
def withinTxSession(tx: Tx = currentTx): DBSession = {
if (!tx.isActive) {
throw new IllegalStateException(ErrorMessage.TRANSACTION_IS_NOT_ACTIVE)
}
DBSession(conn, tx = Some(tx))
}
/**
* Provides within-tx session block.
* @param execution block
* @tparam A return type
* @return result value
*/
def withinTx[A](execution: DBSession => A): A = {
execution(withinTxSession(currentTx))
}
/**
* Provides within-tx session block.
* @param execution block
* @tparam A return type
* @return result value
*/
def withinTxWithConnection[A](execution: Connection => A): A = {
execution(withinTxSession(currentTx).conn)
}
private def begin(tx: Tx): Unit = {
tx.begin()
if (!tx.isActive) {
throw new IllegalStateException(ErrorMessage.TRANSACTION_IS_NOT_ACTIVE)
}
}
private val rollbackIfThrowable = handling(classOf[Throwable]) by {
t =>
tx.rollback()
throw t
}
/**
* Provides local-tx session block.
* @param execution block
* @tparam A return type
* @return result value
*/
def localTx[A](execution: DBSession => A): A = {
using(conn) { conn =>
val tx = newTx
begin(tx)
rollbackIfThrowable[A] {
val session = DBSession(conn, tx = Option(tx))
val result: A = execution(session)
tx.commit()
result
}
}
}
/**
* Provides local-tx session block.
* @param execution block
* @tparam A return type
* @return result value
*/
def localTxWithConnection[A](execution: Connection => A): A = {
using(conn) { conn =>
val tx = newTx
begin(tx)
rollbackIfThrowable[A] {
val session = DBSession(conn, tx = Option(tx))
val result: A = execution(session.conn)
tx.commit()
result
}
}
}
}