我是新手scala和scalatra开发人员。我试图集成c3p0来获取我的应用程序中的连接池。
scalatra页面上的所有示例都是squeryl等,但我不想要orm和dsl。有没有人有scalatra和c3p0的确定例子。
全部谢谢:)
答案 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清洁,请考虑编写类似withStatement
和withResultSet
的方法,这样就可以了
withConnection( request.connectionPool ) { conn =>
withStatement( conn ) { stmt =>
withResultSet( stmt.executeQuery("SELECT * FROM spacemen") ) { rs =>
// read stuff from ResultSet
}
}
}