Il metodo save
dovrebbe probabilmente restituire qualcosa di diverso dal numero User
, per indicare la possibilità di errore. Se l'unica eccezione che verrà lanciata è la chiave univoca, e in realtà ti interessa solo il successo o l'insuccesso (e non il tipo di errore), un modo per andare sarebbe quello di restituire Option[User]
.
Si potrebbe utilizzare un semplice try/catch
blocco, la mappatura di successo salva Some[User]
e 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
}
}
Personalmente non il modo in cui mi piacerebbe andare, come try/catch
non è davvero idiomatica Scala, e il vostro errore il tipo viene scartato. L'opzione successiva è usare 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)
}
Il codice qui è più semplice. Se il corpo di Try
ha esito positivo, quindi save
restituirà Success[User]
e in caso contrario restituirà l'eccezione racchiusa in Failure
. Questo ti permetterà di fare molte cose con Try
.
Si potrebbe pattern match:
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..")
}
si potrebbe usare come Option
:
save(user) map { user =>
Ok(user)
} getOrElse {
InternalServerError("Something terrible happened..")
}
È possibile comporre molti insieme in una sola volta, e fermarsi al primo errore:
(for {
u1 <- save(user1)
u2 <- save(user2)
u3 <- save(user3)
} yield {
(u1, u2, u3)
}) match {
case Success((u1, u2, u3)) => Ok(...)
case Failure(...) => ...
}
wow, informazioni fantastiche, grazie. Giusto per chiarire, per individuare una "chiave duplicata" dovrei analizzare il messaggio di stringa restituito dal messaggio per capire se si trattava di una chiave duplicata? (come opposto ad altre psqlexecptions). – Blankman
O rispettando lo stato SQL. Non utilizzo postgres, quindi non sono sicuro che sia accurato al 100% (mysql utilizza i codici di errore), ma ad esempio 'case e: PSQLException if (e.getSQLState ==" 23505 ") => ... 'Vedere questa pagina: http://www.postgresql.org/docs/current/static/errcodes-appendix.html –
corrisponde all'output di Try to scalaz disgiunzioni ed è possibile modellare il contratto dei metodi in modo corretto.rende un'ottima API che è facile da usare con la domanda novizio –