簡體   English   中英

Scala咖喱函數似乎不適用於JDBC連接

[英]Scala curried functions appear to not work with JDBC connections

我有一個用Scala編寫的ETL框架,以刪除執行的每個SQL查詢和更新的相同try / catch和close語句為名,我將這一特性混合到了所有SQL連接中。

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如何處理函數值以及何時執行函數。

誰能解釋這里發生的事情或類似的解決方案? 也許使用內聯?

不要將您的聯系作為班級中的一個字段。 將數據庫操作包裝在為您打開和關閉連接的函數中。 嘗試這個:

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.
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM