Scalatra与c3p0没有任何额外的库

时间:2013-12-22 13:11:57

标签: c3p0 scalatra

我是新手scala和scalatra开发人员。我试图集成c3p0来获取我的应用程序中的连接池。

scalatra页面上的所有示例都是squeryl等,但我不想要orm和dsl。有没有人有scalatra和c3p0的确定例子。

全部谢谢:)

2 个答案:

答案 0 :(得分:2)

除了Steve的回复之外,您还可以将scala对象用于collectionPoolDataSource,而不是从请求上下文中获取它。

例如,声明:

对象DBDataSource {

private val ds = new ComboPooledDataSource
ds.setDriverClass("org.mariadb.jdbc.Driver")
ds.setUser(dbUser)
ds.setPassword(dbPassword)
ds.setDebugUnreturnedConnectionStackTraces(true)
ds.setUnreturnedConnectionTimeout(7200)
ds.setMaxPoolSize(100)
ds.setMaxStatements(0)
ds.setCheckoutTimeout(60000)
ds.setMinPoolSize(5)
ds.setTestConnectionOnCheckin(true)
ds.setTestConnectionOnCheckout(false)
ds.setBreakAfterAcquireFailure(false)
ds.setIdleConnectionTestPeriod(50)
ds.setMaxIdleTimeExcessConnections(240)
ds.setAcquireIncrement(1)
ds.setAcquireRetryAttempts(5)
ds.setJdbcUrl(dbUrl)
ds.setPreferredTestQuery("SELECT 1")

def datasource = ds

}

您可以在不需要请求上下文的情况下访问数据源:

def withConnection [T](op :( Connection)=> T):T = {     var con:Connection = null

try {
  con = DBDataSource.datasource.getConnection()
  op(con)
} finally {
  attemptClose(con)
}

}

答案 1 :(得分:0)

注意:以下代码都没有编译或检查过,我只是将它写入浏览器。为不可避免的故障道歉。

所以,我从未使用过Scalatra。但我写了c3p0,并且经常使用Servlets API。快速浏览一下scalatra的指南就会发现这样的事情会起作用:

import org.scalatra._
import com.mchange.v2.c3p0._
import javax.sql.DataSource
import javax.servlet.ServletContext

class ScalatraBootstrap extends LifeCycle {

  override def init(context: ServletContext) {
    val cpds = new ConnectionPoolDataSource();

    // perform any c3p0 config operations you might 
    // want here, or better yet, externalize all of 
    // that into a c3p0.properties, c3p0-config.xml,
    // or (c3p0 version 0.9.5 only) application.conf

    context.setAttribute( "appDataSource", cpds );
  }

  override def destroy(context: ServletContext) {
    val cpds = context.getAttribute( "appDataSource" );
    if ( cpds != null ) {
      try {
        cpds.close() 
      } catch {
        case e : Exception => e.printStackTrace(); //consider better logging than this
      }
    }
  }
}

要从ServletRequest对象访问DataSource,您需要调用...

request.getServletContext().getAttribute( "appDataSource" ).asInstanceOf[DataSource]

您可能希望使用Scala-fu来pimp ServletRequest,并使访问连接池更容易和更漂亮。例如,你可以写...

implicit class ConnectionPoolRequest( request : ServletRequest ) {
   def connectionPool : DataSource = request.getServletContext().getAttribute( "appDataSource" ).asInstanceOf[DataSource]
}

将它放在一个包对象或你导入代码的某个对象中,当你处理请求时,你应该能够编写像...这样的东西。

val conn = request.connectionPool.getConnection();
// do stuff
conn.close()

但是,以上是蹩脚,易泄漏的代码,因为close()不在finally中,并且将被异常跳过。在Java7风格中,您可以使用try-with-resources来避免这种情况。在Scala中,天真的方法是这样做:

var conn = null;
try {
  conn = request.connectionPool.getConnection();
  // do stuff
} finally {
  try { if ( conn != null ) conn.close() } catch {
     case e : Exception => e.printStackTrace() // better logging would be nice
  }
}

但是,Scala中更好的方法是定义这样的实用程序方法:

def withConnection[T]( ds : DataSource )( op : (Connection) => T) : T = {
  var con : Connection = null;

  try {
    con = ds.getConnection();
    op(con);
  } finally { 
    attemptClose( con ); 
  }
}

def attemptClose( con : Connection ) {
  if ( con != null ) {
    try { if ( conn != null ) conn.close() } catch {
      case e : Exception => e.printStackTrace() // better logging would be nice
    }
  }
}

然后你可以写出类似......的东西。

withConnection( request.connectionPool ) { conn =>
  // do stuff with the Connection
  // don't worry about cleaning up, that's taken care of for you
}

要在scala中真正保持JDBC清洁,请考虑编写类似withStatementwithResultSet的方法,这样就可以了

withConnection( request.connectionPool ) { conn =>
  withStatement( conn ) { stmt =>
    withResultSet( stmt.executeQuery("SELECT * FROM spacemen") ) { rs =>
      // read stuff from ResultSet
    }
  } 
}