繁体   English   中英

scala中的异常处理

[英]Exception handling in scala

我正在使用Scala处理应用程序。 我试图在应用程序中实现异常处理。 我尝试使用Either来处理异常。 对于简单的情况,似乎足以处理异常。 但是,当我需要通过连接从多个表中获取结果时,异常处理产生的问题多于解决问题。 我的应用程序结构解释如下:

将存储库模式用于定义所有数据库交互操作的数据库操作。 例如,我有一个中央存储库,它定义了findAllfindByIdinsertdeleteupdateexists等。我的findAll方法签名已经改为Either[CustomException, List[TEntity]] ,类似的findById方法类型是Either[CustomException, Option[TEntity]]

现在假设,如果我需要在我的方法中从数据库中获取员工,我将执行以下操作:

def getVehicleById(id:Long) = {

val vehicle = repository.findById(id)
//i have one-to-one mapping with Employee table for the driver of the vehicle
val driver = empRepository.findById(vehicle.driverId)

}

现在车辆的类型将是Either[CustomException, Option[Vehicle]]和驱动程序的类型是Either[CustomException, Employee]

如果我在获得结果后需要再做一些操作,我必须使用右/左案例然后再这样做。 问题是,可能在Right的情况下,我可能需要与另一个表连接,这使得结果再次成为Either[CustomException, Entity] 如果在该操作中发生任何错误,我需要再次使用try catch块。 我觉得当代码复杂性增加时,这种处理变得非常难以管理,而且我将有很多锅炉板代码来处理这些情况,这违反了Scala原则本身。

所以我的问题是,如何在没有太多锅炉板代码的情况下以更好的方式处理异常。

注意:我来自Java背景,现在只在Scala工作了几个月。

编辑

使用Try添加示例代码:此示例非常接近我的要求。

import scala.util._
def checkTry:Try[List[Int]] = Success(List(2))
def checkTryStr:Try[String] = Success("Asd")

def getVehicleWithDriver = for {
  a <- checkTry
  c <- a
  b <- checkTryStr
}yield {
  (c,b)
}
getVehicleWithDriver

但是使用bove代码,我收到了编译错误。

 Error:(9, 6) type mismatch; found : scala.util.Try[(Int, String)] required: scala.collection.GenTraversableOnce[?] b <- checkTryStr ^ Error:(9, 6) type mismatch; found : scala.util.Try[(Int, String)] required: scala.collection.GenTraversableOnce[?] b <- checkTryStr ^ Error:(8, 6) type mismatch; found : List[Nothing] required: scala.util.Try[?] c <- a ^ 

你想使用for / yield糖。 您可以在推杆的习惯得到.right上所有Either S,或@Gangstead表明,使用\\/从Scalaz。 (Scalaz当然有可怕的部分 - 我已经使用它4年了,我仍然被例如Strength吓倒 - 但是完全有可能从简单的部件开始并按照你的方式工作)。

for {
  vehicle <- repository.findById(id).right
  driver <- empRepository.findById(vehicle.driverId).right
  somethingElse <- somePossiblyFailingComputation.right
} yield somethingElse
//Don't need the .right if you're using Scalaz \/

其他重要提示:当您想要将有效函数应用于List时,您希望使用Scalaz traverse

vehicleList <- vehicleIdList.traverse(repository.findById) //assuming you're using \/
//might need a few .right if you're using Either

当你调用Java代码可能抛出一个异常,使用scala.util.control.Exceptioncatching

val myEither = catching(classOf[SomeException]) either someJavaMethodThatThrows()
// (...).disjunction if you're using \/.

如果你需要在使用Either / \\/的同时使用另一种“有效的上下文”,你将不得不开始寻找monad变换器 ,但最好是先使用Either

希望有所帮助; 祝你好运,希望你喜欢斯卡拉。

看看Scalaz的分离\\/

警告:Scalaz是由铁杆人写的硬核scala。

看看Brendon McAdams(@Rit)关于“Scalaz'Gateway Drugs”的演讲。 对于来自Java的程序员来说,他更加平易近人,而且他非常实用

你想使用Try ,而不是Either 它是一个monad,所以你可以mapflatMap它,或者用它for理解。 它实际上看起来很优雅。

def getVehicleWithDriver(id: String): Try [(Vehicle, Driver)] = for {
    vehicle <- repository. findById(id)
    driver <- empRepository.findById(vehicle.driverId)
} yield {
    (vehicle, driver)
}

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM