Quale sarà la migliore pratica per gestire la voce duplicata in DB in Spring MVC, lanciando Exception o in altro modo?

2

Attualmente sto lavorando a un progetto di School Management utilizzando Spring stack, Kotlin come linguaggio di programmazione e Neo4j per la soluzione di storage.

Ecco lo scenario, sto creando una voce di classe nel DB. Supponiamo che le proprietà dell'oggetto di classe Class siano Name: Nine, Section: A, Shift: Morning . Quando sto andando a salvare in DB, devo assicurarmi che non ci sia una classe con le stesse proprietà.

La mia domanda è, dopo la duplicazione, verificare come suppongo di propagare il massaggio all'altro livello o al lato client? Lancia un Exception nel livello in cui ha trovato la duplicazione o qualsiasi altro flusso normale?

Ecco cosa sto gestendo attualmente questo scenario. Fornire Kotlin code.

Controller

open fun post(@RequestBody cls: Course, request: HttpServletRequest): ResponseEntity<*> {        

    try {
        createdClass = classService.save(cls)
    }
    catch (ex: DuplicateCourseException) {            
        return responseConflict(cls)
    }catch (ex: DuplicateKeyException){
        return responseConflict(cls)
    }
    return responseOK(createdClass)
}

Livello di servizio

open fun save(course: Course): Course {
// Checking the DB 
    val foundDuplicate = classRepo.findListByOrganizationName(course.organization?.name)
            .filter {
                it.name == course.name
                it.section == course.section
                it.shift == course.shift
            }
            .isEmpty()
            .not()
    if (foundDuplicate) {
        // Custom Exception
        throw DuplicateCourseException("Duplicate Class Found")
    }
    return classRepo.save(course)
}

O semplicemente controllando dal controller, come il seguente codice

open fun post(@RequestBody cls: Course, request: HttpServletRequest): ResponseEntity<*> {        

    if (classService.checkClassAlreadyExist(cls)) {
         return responseConflict(cls)
     }
   createdClass = classService.save(createdClass)         
   return responseOK(createdClass)
}

Oppure potrei usare un po 'di DTO per comunicare tra il livello di servizio e il controller. E quel DTO ha alcune proprietà, che possono indicare lo stato della voce duplicata trovata. Sono anche consapevole del fatto che ControllerAdvice può gestire Eccezione in modo più elegante.

Quindi avrei bisogno di un suggerimento quale sarà il modo migliore per gestire la voce duplicata in DB?

======= ======= UPDATE

Nel mio caso applicare un vincolo di unicità in DB potrebbe non essere possibile. Ad esempio, le proprietà di una classe possono essere Name: Nine, Section: A, Shift: Morning e un'altra proprietà di classe Name: Nine, Section: A, Shift: Day . In questo caso il vincolo è la combinazione dei valori dell'entità. La stessa combinazione non dovrebbe essere presente in DB. Quindi dovrei controllare l'univocità dal livello dell'applicazione.

    
posta Muztaba Hasanat 16.06.2017 - 00:06
fonte

1 risposta

1

Lavorare con Spring vale la pena attenersi alle sue caratteristiche e funzionalità. A meno che non fossero incompatibili con le tue esigenze, nel qual caso l'utilizzo di Spring sarebbe discutibile.

1. Gestione degli errori

Hai già menzionato l'approccio proposto da Spring. @ControllerAdvice . È possibile implementare un componente dedicato per la gestione degli errori o utilizzare le annotazioni direttamente nei controller.

Questo ridurrà in modo significativo la duplicità di try / catch in tutti i controller.

2. Errori di lancio

È una domanda comune: delegare il controllo dell'integrità dei dati solo al DB?

Di solito sono contro. Per me, i vincoli DB sono l'ultima linea di difesa, non l'unica. Di solito, i vincoli riflettono le regole aziendali, quindi sono favorevole a rendere queste regole esplicite e leggibili lungo il codice.

Non fraintendermi, non sto suggerendo di rimuovere i vincoli di DB. Devono essere . Se ci fossero più sistemi che accedono al DB, ti impediranno violazioni impreviste dell'integrità dei dati.

Indipendentemente se usi eccezioni di violazione dell'integrità dei dati di Spring , eccezioni aziendali o eccezioni modello di dominio, se hai implementato il n. 1, la gestione degli errori rende queste differenze irrilevanti.

Il luogo in cui devono essere generate le eccezioni dipende da te. A causa di questo tipo di eccezioni sono legate al business, non vorrei buttarle dai Controller . Dovrebbero essere il più indipendenti possibile dal business.

Suggerirei di fare le convalide e il lancio dell'errore dal livello del dominio. Lo strato più vicino al DAL. Una cosa importante è essere coerenti con l'implementazione. Ovunque tu decida di fare la validazione, segui questa strategia.

3. La convalida

Invece di recuperare tutta la raccolta

classRepo.findListByOrganizationName(course.organization?.name) 
  .filter { it.name == course.name 
       it.section == course.section 
       it.shift == course.shift }
   .isEmpty() .not()

Perché non fai semplicemente un conteggio delle righe?

classRepo.countByOrganizationName(...)

o

classRepo.existByOrganizationName(...)

4. La domanda

how I suppose to propagate the massage to the other layer or to the client side ?

Dipende. Se i livelli superiori lo cattureranno solo per lanciare la propria eccezione, allora lascia che salga al @ControllerAdvice . Alimentare lo stacktrace delle eccezioni con più tracce non renderà il tuo codice migliore.

Ma, se i livelli superiori possono gestirlo e c'è un Piano B per l'esecuzione fallita, allora prendilo.

Troverete che le eccezioni di Spring DAO sono RuntimeException per una buona ragione ;-).

    
risposta data 16.06.2017 - 07:38
fonte

Leggi altre domande sui tag