我有一个我在Scala中编写的ETL框架,并且为每个SQL查询和我执行的更新删除相同的try / catch和closing语句的名称,我做了这个特性,我混合到我的所有SQL连接。 / p>
trait SqlConnection {
private val defaultHandling = (stmt: PreparedStatement) => stmt.executeUpdate()
protected val con: java.sql.Connection
final def executeSimpleUpdate(sql: String): Unit = executeUpdate(sql)(defaultHandling)
final def executeUpdate[T](sql: String)(statementHandling: PreparedStatement => T) = {
val stmt = con.prepareStatement(sql)
try { statementHandling(stmt) } finally { if (!stmt.isClosed) stmt.close() }
}
final def executeQuery[T](sql: String)(resultHandling: ResultSet => T) = {
val stmt = con.prepareStatement(sql)
try {
val rs = stmt.executeQuery()
try { resultHandling(rs) } finally { if (!rs.isClosed) rs.close() }
} finally { if (!stmt.isClosed) stmt.close() }
}
final def close() = con.close()
}
但是,当我运行它时,没有任何命令被执行。我添加了println
来尝试隔离哪些行或代码没有运行,这给了我这个错误。
Exception in thread "main" com.mysql.jdbc.exceptions.jdbc4.MySQLNonTransientConnectionException: No operations allowed after connection closed.
at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:62)
at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45)
at java.lang.reflect.Constructor.newInstance(Constructor.java:408)
at com.mysql.jdbc.Util.handleNewInstance(Util.java:411)
at com.mysql.jdbc.Util.getInstance(Util.java:386)
at com.mysql.jdbc.SQLError.createSQLException(SQLError.java:1015)
at com.mysql.jdbc.SQLError.createSQLException(SQLError.java:989)
at com.mysql.jdbc.SQLError.createSQLException(SQLError.java:975)
at com.mysql.jdbc.SQLError.createSQLException(SQLError.java:920)
at com.mysql.jdbc.ConnectionImpl.throwConnectionClosedException(ConnectionImpl.java:1320)
at com.mysql.jdbc.ConnectionImpl.checkClosed(ConnectionImpl.java:1312)
at com.mysql.jdbc.ConnectionImpl.prepareStatement(ConnectionImpl.java:4547)
at com.mysql.jdbc.ConnectionImpl.prepareStatement(ConnectionImpl.java:4512)
at util.SqlConnection$class.executeQuery(Connection.scala:50)
我认为我的问题是误解了Scala如何处理函数值以及何时执行函数。
任何人都可以解释这里发生的事情或者类似的解决方案是什么吗?也许使用内联?
答案 0 :(得分:0)
不要将您的连接保持为班级中的字段。将数据库操作包装在一个为您打开和关闭连接的函数中。试试这个:
private def withConnection[A](f: Connection => A): A = {
val con = JDBC.giveMeAConnection()// Do whatever you want to open a connection
val result = f(con)
con.close()
result
}
final def executeQuery[T](sql: String)(resultHandling: ResultSet => T) = withConnection { conn =>
// Use conn as you wish here.
}