简体   繁体   English

scala中的异常处理

[英]Exception handling in scala

I am working on an application with Scala. 我正在使用Scala处理应用程序。 I am trying to implement Exception Handling in the application. 我试图在应用程序中实现异常处理。 I tried using Either for handling the exceptions. 我尝试使用Either来处理异常。 For simple cases, it seems to be enough to handle exceptions. 对于简单的情况,似乎足以处理异常。 However, when I need to get results from multiple tables by joins, the exception handling is creating more issues than solving. 但是,当我需要通过连接从多个表中获取结果时,异常处理产生的问题多于解决问题。 My application structure is explained below: 我的应用程序结构解释如下:

Using repository pattern for the database operations which defines all the database interaction operations. 将存储库模式用于定义所有数据库交互操作的数据库操作。 For eg, I have a central repository which defines findAll , findById , insert , delete , update , exists etc. My findAll methods signature has been changed to Either[CustomException, List[TEntity]] , similarly findById methods type is Either[CustomException, Option[TEntity]] . 例如,我有一个中央存储库,它定义了findAllfindByIdinsertdeleteupdateexists等。我的findAll方法签名已经改为Either[CustomException, List[TEntity]] ,类似的findById方法类型是Either[CustomException, Option[TEntity]]

Now assume that, If I need to fetch employees from database in my method, i will be doing something like below : 现在假设,如果我需要在我的方法中从数据库中获取员工,我将执行以下操作:

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)

}

Now the type of vehicle will be Either[CustomException, Option[Vehicle]] and type of driver is Either[CustomException, Employee] 现在车辆的类型将是Either[CustomException, Option[Vehicle]]和驱动程序的类型是Either[CustomException, Employee]

If i need to do any more operation after getting the results, i have to use case Right/Left and then do that. 如果我在获得结果后需要再做一些操作,我必须使用右/左案例然后再这样做。 The problem is that, may be inside the Right case, I might need to join with another table, which makes the result of that as again Either[CustomException, Entity] . 问题是,可能在Right的情况下,我可能需要与另一个表连接,这使得结果再次成为Either[CustomException, Entity] if any error occurs in that operation, i need to again use try catch block. 如果在该操作中发生任何错误,我需要再次使用try catch块。 I feel that this kind of hanling becomes very difficult to manage when the code complexity increases, and also I will have a lot of boiler plate code to handle these situations, which goes against Scala principle itself. 我觉得当代码复杂性增加时,这种处理变得非常难以管理,而且我将有很多锅炉板代码来处理这些情况,这违反了Scala原则本身。

So my question is, how can I handle exception in a better way without much boiler plate code. 所以我的问题是,如何在没有太多锅炉板代码的情况下以更好的方式处理异常。

Note : I am coming from a Java background, have been working on Scala only for a couple of months now. 注意:我来自Java背景,现在只在Scala工作了几个月。

EDIT 编辑

Adding Sample Code with Try : This sample is very close to the requirement I have. 使用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

But with the bove code, I am getting compilation errors. 但是使用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 ^ 

You want to use the for / yield sugar. 你想使用for / yield糖。 You can either get in the habit of putting .right on all your Either s, or as @Gangstead suggests, use \\/ from Scalaz. 您可以在推杆的习惯得到.right上所有Either S,或@Gangstead表明,使用\\/从Scalaz。 (There are certainly scary parts of Scalaz - I've been using it for 4 years and am still intimidated by eg Strength - but it's perfectly possible to start with the easy parts and work your way up). (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 \/

Other vital hints: when you want to apply an effectful function to a List, you want to use Scalaz traverse : 其他重要提示:当您想要将有效函数应用于List时,您希望使用Scalaz traverse

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

When you're calling Java code that might throw an exception, use scala.util.control.Exception 's catching : 当你调用Java代码可能抛出一个异常,使用scala.util.control.Exceptioncatching

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

If you need to work with another kind of "effectful context" at the same time as working with Either / \\/ , you'll have to start looking at monad transformers , but it might be best to get comfortable with just Either first. 如果你需要在使用Either / \\/的同时使用另一种“有效的上下文”,你将不得不开始寻找monad变换器 ,但最好是先使用Either

Hope that helps; 希望有所帮助; best of luck, hope you like Scala. 祝你好运,希望你喜欢斯卡拉。

Take a look at Scalaz's disjunction \\/ . 看看Scalaz的分离\\/

A warning: Scalaz is hardcore scala written by hardcore guys. 警告:Scalaz是由铁杆人写的硬核scala。

Take a look at Brendon McAdams' (@Rit) presentation about "Scalaz' Gateway Drugs" . 看看Brendon McAdams(@Rit)关于“Scalaz'Gateway Drugs”的演讲。 He's much more approachable for programmers coming from Java, and he keeps it very practicall 对于来自Java的程序员来说,他更加平易近人,而且他非常实用

You want to use Try , not Either . 你想使用Try ,而不是Either It is a monad, so you can map or flatMap it, or use it in a for comprehension. 它是一个monad,所以你可以mapflatMap它,或者用它for理解。 It looks pretty elegant actually. 它实际上看起来很优雅。

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