6

我试图避免可变变量,但问题是我必须访问我需要在 try 中初始化的 val(这是一个可能失败的 db 操作),并且我需要在 finally 块中使用该 var

我尝试了几种选择:

在 try 块中声明 val

try {
  val resultSet = SQL(sql).resultSet
  return ColumnInfo(resultSet.getMetaData)
} catch {
  case e => throw new ColumnInfoException("Error getting metadata")
} finally {
  resultSet.close
}

error: not found: value resultSet

在 try 块之外声明 val 而不初始化它

val resultSet: java.sql.ResultSet
try {
  resultSet = SQL(sql).resultSet
  return ColumnInfo(resultSet.getMetaData)
} catch {
  case e => throw new ColumnInfoException("Error getting metadata")
} finally {
  resultSet.close
}

error: only classes can have declared but undefined members

使用 var,这似乎有效

var resultSet: java.sql.ResultSet = null
try {
  resultSet = SQL(sql).resultSet
  return ColumnInfo(resultSet.getMetaData)
} catch {
  case e => throw new ColumnInfoException("Error getting metadata")
} finally {
  resultSet.close
}

最后嵌套 try-catch 块,这看起来很脏

try {
  val resultSet = SQL(sql).resultSet
  try {
    return ColumnInfo(resultSet.getMetaData)
  } catch {
    case e => throw new ColumnInfoException("Error getting metadata")
  } finally {
    resultSet.close
  }
} catch {
  case e => throw new ColumnInfoException("Error opening resultSet")
}

我可以采取一些更好的方法来避免使用 vars 和嵌套 try-catch 块吗?

4

4 回答 4

3
import scala.util.control.Exception._

allCatch.either(SQL(sql).resultSet).right.flatMap{ resultSet =>
  val ans = allCatch.either(ColumnInfo(resultSet.getMetaData))
  resultSet.close
  ans
}.fold(e => throw e, identity)

或者您可以跳过fold并将异常打包在Left.

于 2012-09-11T06:08:42.477 回答
2

In Scala, try block is an expression. In your case it can evaluate to a tuple containing both vals:

val res: (java.sql.ResultSet, ColumnInfo) = try {
  val rs = SQL(sql).resultSet
  (rs, ColumnInfo(rs.getMetaData))
} catch {
  case _: Throwable => throw new Exception("Error getting metadata")
} finally {
  res._1.close
}
val columnInfo = res._2
于 2014-10-08T10:05:16.607 回答
2

从这个问题函数try & catch w/Scala

我了解了贷款模式:https ://wiki.scala-lang.org/display/SYGN/Loan

Play 框架本身似乎将它与 DB.withConnection 方法一起使用

于 2012-09-11T05:17:16.930 回答
0

摆脱第一个 catch 块:

try {
  val resultSet = SQL(sql).resultSet
  try {
    ColumnInfo(resultSet.getMetaData)
  } finally {
    resultSet.close
  }
} catch {
  case e => throw new ColumnInfoException("Error opening resultSet")
}
于 2012-09-11T05:17:43.230 回答