如何使用函数式编程风格在Scala中管理数据库连接? [英] How to manage DB connection in Scala using functional programming style?

查看:72
本文介绍了如何使用函数式编程风格在Scala中管理数据库连接?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一段使用数据库连接的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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆