2012-07-16 13 views
6

Attualmente sto giocando con Play 2.0 (Scala). Devo ammettere che è molto divertente. Ho una domanda però relativa alle eccezioni operazioni database.Come gestire le eccezioni relative al DB in gioco! 2.0/Scala con Anorm

Diciamo che ho Car come una classe di dominio e che ho un vincolo di integrità su uno dei campi, diciamo che il modello modo che nel db non può avere due (2) file che hanno la stesso nome del modello:

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

sto cercando di inserire un record nel DB in questo modo:

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 
     } 
    } 
} 

se non intercettare l'eccezione, come nel codice precedente, poi, quando io chiamo questo metodo dal mio controller con il modello che ha un valore già esistente nel database, ho il seguente eccezione generata:

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

C'è un modo per prendere il MySQLIntegrityConstraintViolationException invece di Eccezione in modo da avere un Fine- ad esempio il controllo su cosa può andare storto e quindi fornire un feed-back più conciso al mio utente, ad esempio (in un browser o su un dispositivo mobile)?

È questo il modo migliore per gestire le operazioni e le eccezioni relative al DB oppure esistono delle best practice che tutti utilizzano?

grazie in anticipo,

risposta

2

penso che si sta cercando qualcosa all'interno di queste linee:

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

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

Nota importante: assicurarsi di importare com.mysql.jdbc.exceptions.jdbc4.MySQLIntegrityConstraintViolationException, e non com.mysql.jdbc.exceptions.MySQLIntegrityConstraintViolationException. Più precisamente, assicurati che l'importazione corrisponda all'eccezione nella traccia dello stack.

Per quanto riguarda le best practice, non so come sto giocando anche con questo framework :).

Come per il feedback per l'utente ... forse il Flash Scope è un buon modo per comunicare one-liner alla 'pagina successiva' (ad esempio se l'auto è stata memorizzata correttamente o meno). Vedere: http://www.playframework.org/documentation/2.0/ScalaSessionFlash (scorrere fino a 'ambito Flash'.)

+1

ho cercato di intercettare l'eccezione MySQLIntegrityConstraintViolationException come questo, ma non sta funzionando. Probabilmente perché MySQLIntegrityConstraintViolationException non è una case case e quindi non è idoneo per il pattern matching. – kaffein

+1

@kaffein Le classi non-case possono essere abbinate semplicemente, non è possibile decostruirle, ad es. non puoi fare 'case NonCaseClass (e) =>', perché di default non hanno un metodo unpply. Nel mio caso il problema era un'importazione errata. Ho importato 'com.mysql.jdbc.exceptions.MySQLIntegrityConstraintViolationException' invece di' com.mysql.jdbc.exceptions.jdbc4.MySQLIntegrityConstraintViolationException' (notare il pacchetto 'jdbc4'). –

1

sto lavorando in un po 'diverso, ma parco giochi, per quanto ho capito, ho risolto lo stesso problema. Sto lavorando con liftweb, maven e scala 2.9.

L'eccezione viene completata con RuntimeException. Per catturarlo, rilevo RuntimeException ed esamina la sua causa. Nel caso in cui si tratti di una violazione di un vincolo, faccio i miei affari, altrimenti restituisco l'eccezione. Vedere il seguente codice:

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

Se la generazione non riesce con il seguente errore:

error: object mysql is not a member of package com 

verifica la definizione di pacchetto mysql su Maven pom. Nel mio caso è stato definito come ambito di runtime. La sua modifica in ambito di compilazione ha permesso alla build di avere successo e in runtime questa cattura funziona correttamente. Ecco sezione dipendenza mysql in Maven pom.xml:

<dependency> 
     <groupId>mysql</groupId> 
     <artifactId>mysql-connector-java</artifactId> 
     <version>5.1.18</version> 
     <scope>runtime</scope> 
    </dependency> 
Problemi correlati