Ответ 1
Ваш метод save
должен, вероятно, возвращать что-то другое, чем просто User
, чтобы указать на возможность сбоя. Если единственное исключение, которое будет выбрано, - это уникальный ключ, и вы действительно заботитесь об успехе или неудаче (а не о типе сбоя), один из способов - вернуть Option[User]
.
Вы можете использовать простой блок try/catch
, сопоставление успешных сохраняет до Some[User]
и PSQLException
до None
:
def save(user: User)(implicit session: Session): Option[User] = {
try {
val newId = (users returning users.map(_id) += user
Some(user.copy(id = newId))
} catch {
case PSQLException => None
}
}
Лично не так, как я бы сказал, поскольку try/catch
не является действительно идиоматическим Scala, и ваш тип ошибки отбрасывается. Следующая опция - использовать scala.util.Try
.
def save(user: User)(implicit session: Session): Try[User] = Try {
val newId = (users returning users.map(_id) += user
user.copy(id = newId)
}
Код здесь проще. Если тело Try
успешное, то save
вернет Success[User]
, и если нет, оно вернет исключение, завернутое в Failure
. Это позволит вам делать много вещей с помощью Try
.
Вы можете сопоставить образ:
save(user) match {
case Success(user) => Ok(user)
case Failure(t: PSQLException) if(e.getSQLState == "23505") => InternalServerError("Some sort of unique key violation..")
case Failure(t: PSQLException) => InternalServerError("Some sort of psql error..")
case Failure(_) => InternalServerError("Something else happened.. it was bad..")
}
Вы можете использовать его как Option
:
save(user) map { user =>
Ok(user)
} getOrElse {
InternalServerError("Something terrible happened..")
}
Вы можете скомпоновать много вместе и остановить первый сбой:
(for {
u1 <- save(user1)
u2 <- save(user2)
u3 <- save(user3)
} yield {
(u1, u2, u3)
}) match {
case Success((u1, u2, u3)) => Ok(...)
case Failure(...) => ...
}