Utilisation de génériques dans les référentiels Spring Data JPA

J’ai un certain nombre de types d’objects simples qui doivent être conservés dans une firebase database. J’utilise Spring JPA pour gérer cette persistance. Pour chaque type d’object, j’ai besoin de construire les éléments suivants:

import org.springframework.data.jpa.repository.JpaRepository; public interface FacilityRepository extends JpaRepository { } public interface FacilityService { public Facility create(Facility facility); } @Service public class FacilityServiceImpl implements FacilityService { @Resource private FacilityRepository countryRepository; @Transactional public Facility create(Facility facility) { Facility created = facility; return facilityRepository.save(created); } } 

Je me suis dit qu’il serait peut-être possible de remplacer les classes multiples pour chaque type d’object par trois classes basées sur des génériques, économisant ainsi beaucoup de codage passe-partout. Je ne sais pas exactement comment s’y prendre et en fait si c’est une bonne idée?

Tout d’abord, je sais que nous soulevons la barre un peu, mais c’est déjà énormément moins de code que ce que vous aviez à écrire sans l’aide de Spring Data JPA.

Deuxièmement, je pense que vous n’avez pas besoin de la classe de service en premier lieu, si vous ne faites que transférer un appel au référentiel. Nous vous recommandons d’utiliser des services devant les référentiels si vous disposez d’une logique métier nécessitant l’orchestration de différents référentiels au sein d’une transaction ou si une autre logique métier doit être encapsulée.

De manière générale, vous pouvez bien sûr faire quelque chose comme ceci:

 interface ProductRepository extends CrudRepository { @Query("select p from #{#entityName} p where ?1 member of p.categories") Iterable findByCategory(Ssortingng category); Iterable findByName(Ssortingng name); } 

Cela vous permettra d’utiliser le repository du côté client comme ceci:

 class MyClient { @Autowired public MyClient(ProductRepository carRepository, ProductRepository wineRepository) { … } } 

et cela fonctionnera comme prévu. Cependant, il y a quelques points à noter:

Cela ne fonctionne que si les classes de domaine utilisent l’inheritance d’une seule table. La seule information à propos de la classe de domaine que nous pouvons obtenir au moment du démarrage est que ce sera des objects Product . Ainsi, pour les méthodes telles que findAll() et même findByName(…) les requêtes pertinentes commenceront par select p from Product p where… . Cela est dû au fait que la recherche de reflection ne pourra jamais produire Wine ou Car moins que vous ne créiez une interface de référentiel dédiée pour capturer les informations de type concrètes.

De manière générale, nous vous recommandons de créer des interfaces de référentiel par racine agrégée . Cela signifie que vous n’avez pas de repo pour chaque classe de domaine en soi. Plus important encore, une abstraction 1: 1 d’un service sur un référentiel est également totalement absente. Si vous construisez des services, vous n’en créez pas pour chaque repository (un singe pourrait le faire, et nous ne sums pas des singes, n’est-ce pas?). Un service expose une API de niveau supérieur, constitue un lecteur beaucoup plus pratique et orchestre généralement les appels à plusieurs référentiels.

En outre, si vous créez des services au-dessus des référentiels, vous souhaitez généralement forcer les clients à utiliser le service au lieu du référentiel (un exemple classique est qu’un service de gestion des utilisateurs déclenche également la génération de mot de passe et le chiffrement). ce serait une bonne idée de laisser les développeurs utiliser le référentiel directement car ils travailleraient efficacement autour du chiffrement). Donc, vous voulez généralement être sélectif sur qui peut persister quels objects de domaine ne pas créer de dépendances partout.

Résumé

Oui, vous pouvez créer des référentiels génériques et les utiliser avec plusieurs types de domaines, mais il existe des limitations techniques assez ssortingctes. Néanmoins, d’un sharepoint vue architectural, le scénario que vous décrivez ci-dessus devrait même apparaître car cela signifie de toute façon que vous faites face à une odeur de design.