2012-07-16 8 views
6

Ich bin derzeit Play! Ing mit Play 2.0 (Scala). Ich muss zugeben, dass es sehr viel Spaß macht. Ich habe eine Frage im Zusammenhang mit Datenbankoperationen Ausnahmen.Wie man DB bezogene Ausnahmen im Spiel verwaltet! 2.0/Scala mit Anorm

Sagen wir, ich Auto als Domain-Klasse haben und dass ich eine Integritätsbedingung auf einem Feld haben, lassen Sie uns sagen, dass das Modell, so dass in der db ich nicht zwei haben kann (2) Reihen der mit gleiche Modellname:

case class Car(id: Pk[Long], name: String, model: String) 

ich versuche, einen Datensatz in der DB wie folgt einzufügen:

def create(car: Car): Option[Long] = { 
    DB.withConnection { implicit connection => 
     try { 
      SQL("insert into cars (name, model) values ({name},{model}").on("name" -> car.name, "model" -> car.model).executeInsert() 
     } catch { 
      case e: Exception => { 
      Logger.debug(e.getMessage()) 
      None 
     } 
    } 
} 

wenn ich im vorigen Code nicht wie die Ausnahme abfangen, dann, wenn ich das nennen Methode von meinem Controller mit dem Modell einen Wert bereits bestehenden in der Datenbank hat, habe ich die folgende Ausnahme ausgelöst:

com.mysql.jdbc.exceptions.jdbc4.MySQLIntegrityConstraintViolationException: Duplicate entry 'Enzo' for key 'model' 

Gibt es eine Möglichkeit, die MySQLIntegrityConstraintViolationException statt Ausnahme so, dass ich eine fein- haben zu fangen genauste Kontrolle darüber, was schiefgehen kann und dann beispielsweise meinem Benutzer ein präziseres Feedback geben (in einem Browser oder auf einem mobilen Gerät)?

Ist dies der beste Weg, DB-bezogene Operationen und Ausnahmen zu behandeln, oder gibt es Best Practices, die jeder nutzt?

Vielen Dank im Voraus,

Antwort

2

Ich glaube, Sie wie etwas in dieser Richtung suchen:

import com.mysql.jdbc.exceptions.jdbc4.MySQLIntegrityConstraintViolationException 

catch { 
    case e:MySQLIntegrityConstraintViolationException => Logger.debug("Whoops") 
    case e:Exception => { 
    Logger.debug(e.getMessage()) 
    None 
    } 
} 

Wichtiger Hinweis: Stellen Sie sicher, dass Sie importieren com.mysql.jdbc.exceptions.jdbc4.MySQLIntegrityConstraintViolationException und nicht com.mysql.jdbc.exceptions.MySQLIntegrityConstraintViolationException. Genauer gesagt, stellen Sie sicher, dass Ihr Import mit der Ausnahme in Ihrer Stack-Ablaufverfolgung übereinstimmt.

Wie für Best-Practices, ich weiß nicht, wie ich auch mit diesem Rahmen spiele :).

Wie für die Rückmeldung an den Benutzer ... vielleicht ist der Flash Scope eine gute Möglichkeit, One-Liner auf der "nächsten Seite" zu kommunizieren (z. B. wenn das Auto erfolgreich gespeichert wurde oder nicht). Siehe: http://www.playframework.org/documentation/2.0/ScalaSessionFlash (Scrollen Sie nach unten zu "Flash scope".)

+1

Ich versuchte, die MySQLIntegrityConstraintViolationException Ausnahme wie diese zu fangen, aber es funktioniert nicht. Wahrscheinlich, weil MySQLIntegrityConstraintViolationException keine Fallklasse ist und dann nicht für die Mustererkennung geeignet ist. – kaffein

+1

@kaffein nicht-Case-Klassen können auf gut abgestimmt werden, Sie können sie nicht einfach dekonstruieren, z. Sie können 'case NonCaseClass (e) =>' nicht ausführen, da sie standardmäßig keine Methode zum Aufheben der Anwahl haben. In meinem Fall war das Problem ein falscher Import. Ich habe 'com.mysql.jdbc.exceptions.MySQLIntegrityConstraintViolationException' anstelle von' com.mysql.jdbc.exceptions.jdbc4.MySQLIntegrityConstraintViolationException' importiert (beachten Sie das Paket 'jdbc4'). –

1

Ich arbeite in einem etwas anderen Spielplatz, aber, soweit ich verstehe, habe ich das gleiche Problem gelöst. Ich arbeite mit Liftweb, Maven und Scala 2.9.

Die Ausnahme wird mit RuntimeException umgebrochen. Um es zu fangen, fange ich RuntimeException und untersuche seine Ursache. Wenn es eine Constraint-Verletzung ist, mache ich meine Sache, sonst werfe ich die Ausnahme zurück. Siehe den folgenden Code:

import com.mysql.jdbc.exceptions.jdbc4.MySQLIntegrityConstraintViolationException 
... 
    } catch { 
     case e: RuntimeException => { 
     e.getCause match { 
      case cause: MySQLIntegrityConstraintViolationException => { 
      ... 
      } 
      case _ => throw e 
     } 
     } 
    } 

Wenn der Build mit dem folgenden Fehler fehl:

error: object mysql is not a member of package com 

Überprüfen Sie die Definition von mysql-Paket auf Maven pom. In meinem Fall wurde es als Laufzeitumfang definiert. Wenn Sie den Bereich zum Kompilieren ändern, kann der Build erfolgreich ausgeführt werden. In der Laufzeit funktioniert dieser Catch ordnungsgemäß. Hier ist mysql dependancy Abschnitt in Maven pom.xml:

<dependency> 
     <groupId>mysql</groupId> 
     <artifactId>mysql-connector-java</artifactId> 
     <version>5.1.18</version> 
     <scope>runtime</scope> 
    </dependency> 
Verwandte Themen