如何使用函数式编程风格在Scala中管理数据库连接? [英] How to manage DB connection in Scala using functional programming style?
问题描述
我有一段使用数据库连接的Scala代码:
I have a piece of Scala code using DB connection:
def getAllProviderCodes()(implicit conf : Configuration) : List[String] = {
var conn: java.sql.Connection = null
try {
conn = DriverManager.getConnection(DBInfo.dbUrl(conf), DBInfo.dbUserName(conf), DBInfo.dbPassword(conf))
return ResultSetIterator.create(
conn.prepareStatement("SELECT pcode FROM providers").executeQuery()
){_.getString("pcode")}.toList
} catch {
case e: Exception =>
logger.warn("Something went wrong with creating the connection: " + e.getStackTrace)
} finally {
if (conn != null) {
conn.close()
}
}
List()
}
这是一种非常类似于OOP-Java的样式,所以我想知道是否有一种以更多功能的方式编写它的方法?我尝试成功应用尝试 monad,但失败了:我最大的担心是,我们在这里已经声明了,以及 finally
块。这类情况也许有某种模式?
It's very OOP-Java-like style, so I'd like to know is there a way to write it in more functional way? I tried to succeed in applying Try monad, but failed: my biggest concern is that we have state here, as well as finally
block. Maybe there's some kind of pattern for such cases?
谢谢。
UPD:这是此处恕我直言,解决方案将如下所示:
UPD: Here's the example from here of what IMHO the solution will look like:
val connection = database.getConnection()
val data: Seq[Data] = Try{
val results = connection.query("select whatever")
results.map(convertToWhatIneed)
} recover {
case t: Throwable =>
Seq.empty[Data]
} get
connection.close()
但是正如我在评论中提到的那样,我必须关闭连接,然后我必须将与连接有关的所有内容放置在内部,尝试使其保持纯净...然后,我将变量与 try -catch-finally在Try块中。
But as I've mentioned in the comment, I have to close the connection, then I have to place all the things regarding to connection inside Try to keep it pure... and then I to the variant with "try-catch-finally" inside Try block.
推荐答案
我从没玩过Java SQL Connection库,因此我的答案已经写成伪代码,但是如果我正确理解了您的问题,这里就是我将如何执行您所做的事情:
I've never played around with the Java SQL Connection library so the syntax of my answer has been written as pseudocode, but if I understand your question correctly here is how I would implement what you have done:
def getAllProviderCodes()(implicit conf : Configuration): List[String] = {
val conn: Connection = DriverManager.getConnection(???) // replace ??? with parameters
val result: List[String] = Try {
??? // ResultSetIterator stuff
} match {
case Success(output) => output // or whatever .toList thing
case Failure(_) => List.empty // add logging here
}
if(conn != null) conn.close()
result // will be whatever List you make (or an empty List if Try fails)
}
而不是类似Java的 try-catch-finally
块,一种类似于Scala的处理方式是将可能爆炸的东西放在 Try
块中,使用 case Success(out)
和 case Failure(ex)
将响应分配给一个值。
Instead of a Java-like try-catch-finally
block, one Scala-like way of doing things would be to put the stuff which could explode in a Try
block and assigning the response to a value using case Success(out)
and case Failure(ex)
.
这篇关于如何使用函数式编程风格在Scala中管理数据库连接?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!