web-dev-qa-db-fra.com

Quelle sera la meilleure pratique pour gérer l'entrée en double dans dB au printemps MVC, lancer une exception ou une autre manière?

Je travaille actuellement sur un projet de gestion de l'école à l'aide de Spring Stack, Kotlin en tant que langage de programmation et NEO4J pour la solution de stockage.

Voici le scénario, je crée une entrée de classe dans la DB. Permet de supposer que les propriétés de l'objet d'entité de classe sont Name: Nine, Section: A, Shift: Morning. Quand je vais économiser dans DB, je dois m'assurer qu'il n'y a pas de classe de ce type qui a les mêmes propriétés.

Ma question est, après la double duplication, vérifiez comment je suppose de propager le massage à l'autre couche ou au côté du client? Lancer un Exception dans la couche où il a trouvé la duplication ou tout autre écoulement normal?

Voici ce que je gère actuellement ce scénario. Fournir Kotlin code.

contrôleur

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

couche de service

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

Ou juste vérifier à partir du contrôleur, comme le code suivant

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

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

Ou je pourrais utiliser quelque chose DTO pour communiquer entre la couche de service et le contrôleur. Et que DTO a des propriétés, cela peut indiquer l'état de l'entrée en double trouvée. Je suis également conscient que ControllerAdvice peut gérer des exceptions plus élégamment.

Donc, j'aurais besoin de suggestion quelle sera la meilleure façon de gérer l'entrée en double dans dB?

======= mise à jour =======

Dans mon cas, appliquer la contrainte d'unicité dans la DB peut ne pas être possible. Par exemple, une classe de classe peut être Name: Nine, Section: A, Shift: Morning et une autre propriété de classe Name: Nine, Section: A, Shift: Day. Dans ce cas, la contrainte est la combinaison des valeurs de l'entité. La même combinaison ne doit pas exister dans dB. Donc, je pourrais avoir à vérifier l'unicité de la couche d'application.

2
Muztaba Hasanat

Travailler avec le printemps valant la peine de s'en tenir à ses caractéristiques et ses capacités. À moins qu'ils n'étaient incompatibles avec vos exigences, auquel cas l'utilisation du printemps serait discutable.

1. Manipulation des erreurs

Vous avez déjà mentionné l'approche proposée au printemps. @ contrôleurAdvice. Vous pouvez implémenter un composant dédié pour la manipulation d'erreurs ou utiliser les annotations directement dans les contrôleurs.

Cela réduira considérablement la duplicité de TRY/CATCH blocs dans tous les contrôleurs.

2. Erreurs de lancer

C'est une question commune: Dois-je déléguer le contrôle de l'intégrité des données uniquement à la DB ?

Je suis généralement contre. Pour moi, les contraintes de la DB sont la dernière ligne de défense, pas la seule. Habituellement, les contraintes reflètent les règles commerciales, donc je suis en faveur de la création de ces règles explicite et lisible le long du code.

Ne vous méprenez pas, je ne suggère pas de supprimer les contraintes de DB. Ils doivent être . S'il y avait plus de systèmes accessibles à la DB, ils vous empêcheront de violations inattendues de l'intégrité des données.

Si vous utilisez Exceptions de violation de l'intégrité des données de printemps, exceptions commerciales ou exceptions de modèle de domaine, si vous avez implémenté le numéro 1, la manipulation des erreurs permet de négliger ces différences.

L'endroit où les exceptions doivent être levées dépend de vous. En raison de ces exceptions, je ne les jette pas à partir de contrôleurs. Ils devraient être aussi agnostiques pour l'entreprise que possible.

Je suggérerais de faire les validations et l'erreur à jeter de la couche de domaine. La couche plus proche du dal. Une chose importante est d'être cohérente avec la mise en œuvre. Où que vous décidiez de faire la validation, tenez-vous à une telle stratégie.

3. La validation

Au lieu de récupérer toute la collection

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

Pourquoi ne faites-vous pas simplement un compte des rangées?

classRepo.countByOrganizationName(...)

ou

classRepo.existByOrganizationName(...)

4. La question

comment je suppose de propager le massage à l'autre couche ou au côté du client?

Dépend. Si les couches supérieures vont simplement l'attraper pour jeter sa propre exception, laissez-la simplement aller jusqu'au @ contrôleurAdvice. Nourrir l'exception StackTrace avec plus de traces ne fera que mieux votre code.

Mais si les couches supérieures peuvent traiter avec elle et il y a un plan b pour l'exécution échouée, puis attrapez-la.

Vous constaterez que les exceptions de Spring Dao sont des exceptions runtimédies pour une bonne raison ;-).

1
Laiv