web-dev-qa-db-fra.com

Modèle de référentiel - Comment le comprendre et comment fonctionne-t-il avec des entités "complexes"?

J'ai du mal à comprendre le modèle de référentiel.

Il y a beaucoup d'opinions sur ce sujet comme dans modèle de référentiel bien fait mais aussi d'autres choses comme le référentiel est le nouveau Singleton ou encore comme dans ne pas utilisez DAO use Repository ou prenez juste Spring JPA Data + Hibernate + MySQL + MAVEN où un dépôt semble être identique à un objet DAO.

Je commence à en avoir marre de lire ce genre de choses car, à mon humble avis, cela ne peut pas être une chose aussi difficile que celle présentée dans de nombreux articles.

Je le vois comme ceci: Il semble que ce que je veux ressemble à ceci:

         ------------------------------------------------------------------------
         |                            Server                                    |
         ------------------------------------------------------------------------
         |                    |                        |                        |
Client <-|-> Service Layer  <-|->  Repository Layer  <-|-> ORM / Database Layer |
         |                    |                        |                        |  
         ------------------------------------------------------------------------

Le Service Layer Prend les objets *DTO Et les transmet au Repository Layer Qui n’est fondamentalement rien de plus que "le type" qui sait comment une entité peut être stockée.

Par exemple, supposons que vous ayez une composition de quelques outils (, notez qu'il s'agit simplement d'un pseudo-code )

@Entity
class ToolSet {
  @Id
  public Long id;
  @OneToOne
  public Tool tool1;
  @OneToOne
  public Tool tool2;
}

@Entity
class Tool {
  @Id
  public Long id;
  @OneToMany
  public ToolDescription toolDescription;
}

@Entity
class ToolDescription {
  @Id
  public Long id;
  @NotNull
  @OneToOne
  public Language language

  public String name;
  public String details;
}

Ce que je ne reçois pas, c'est la partie où je reçois un objet ToolSetDTO du client.

Si j'ai bien compris, je pourrais écrire un ToolSetRepository avec une méthode ToolSetRepository.save(ToolSetDTO toolSetDto) que " sait comment stocker "a ToolSetDTO. Mais presque tous les tutoriels ne passent pas le *DTO Mais le Entity à la place.

Ce qui me dérange ici, c’est que si vous prenez mon exemple ToolSet ci-dessus, je devrais suivre les étapes suivantes:

  1. Prenez toolSetDto et vérifiez si null
  2. Pour chaque tool*Dto Appartenant à toolSetDto
    a) Si a un identifiant valide, convertir de DTO en Entity sinon créer une nouvelle entrée de base de données
    b) toolDescriptionDto et le convertir/l'enregistrer dans la base de données ou créer une nouvelle entrée
  3. Après avoir vérifié ceux ci-dessus, instanciez ToolSet (entité) et configurez-le pour le conserver dans la base de données.

Tout cela est trop complexe pour laisser simplement la fonction de service (interface pour le client) s'en charger.

Ce à quoi je pensais, c'était créer, par exemple. un ToolSetRepository mais la question ici est

  • Accepte-t-il un objet entité ToolSet ou utilise-t-il un objet DTO?
  • Dans tous les cas: le *Repository Est-il autorisé à utiliser d'autres objets du référentiel? Comme lorsque je veux enregistrer ToolSet mais que je dois stocker Tool et ToolDescription en premier - utiliserais-je ToolRepository et ToolDescriptionRepository à l'intérieur ToolSetRepository?
    Si oui: Pourquoi cela ne casse-t-il pas le modèle de référentiel? Si ce modèle est fondamentalement une couche entre le service et mon framework ORM, il ne faut pas "se sentir bien" pour ajouter des dépendances à d'autres classes *Repository Pour des raisons de dépendance.

Je ne sais pas pourquoi je n'arrive pas à comprendre. Cela ne semble pas que compliqué, mais il existe toujours une aide telle que Spring Data. Une autre chose qui me dérange, car je ne vois vraiment pas en quoi cela facilite quoi que ce soit . Surtout que j'utilise déjà Hibernate - je ne vois pas l'avantage (mais c'est peut-être une autre question).

Donc .. Je sais que la question est longue mais j’ai déjà consacré quelques jours à la recherche. Je travaille actuellement sur du code existant qui commence à devenir un gâchis parce que je ne peux tout simplement pas voir à travers ce modèle.

J'espère que quelqu'un pourra me donner une image plus grande que la plupart des articles et des tutoriels qui ne vont pas au-delà de la mise en œuvre d'un exemple très simple de modèle de référentiel.

62
displayname

Vous pouvez lire mon "référentiel pour les nuls" post pour comprendre le principe simple du référentiel. Je pense que votre problème est que vous travaillez avec des DTO et que dans ce scénario, vous n'utilisez pas vraiment le modèle de référentiel, vous utilisez un DAO.

La principale différence entre un référentiel et un dao est qu'un référentiel ne renvoie que des objets compris par la couche appelante . La plupart du temps, le référentiel est utilisé par la couche de gestion et renvoie donc des objets de gestion. Un DAO renvoie des données qui peuvent ou non être un objet métier complet, c’est-à-dire qu’elles ne sont pas un concept commercial valide.

Si vos objets métier ne sont que des structures de données, il est possible que vous ayez un problème de modélisation, c'est-à-dire une mauvaise conception. Un référentiel a plus de sens avec des objets "riches" ou du moins correctement encapsulés. Si vous ne faites que charger/sauvegarder des structures de données, vous n'avez probablement pas besoin d'un référentiel, orm suffit.

Si vous traitez avec des objets métier composés d'autres objets (un agrégat) et que cet objet a besoin de toutes ses parties pour être cohérent (un racine agrégée) alors le modèle de référentiel est la meilleure solution car il va résumer tous les détails de persistance. Votre application demandera simplement un "Produit" et le référentiel le renverra dans son ensemble, quel que soit le nombre de tables ou de requêtes nécessaires pour restaurer l'objet.

Sur la base de votre exemple de code, vous n'avez pas de "vrais" objets métier. Vous avez des structures de données utilisées par Hibernate. Un objet métier est conçu en fonction de concepts métier et de cas d'utilisation. Le référentiel permet au BL de ne pas se soucier de la persistance de cet objet. D'une certaine manière, un référentiel agit comme un "convertisseur/mappeur" entre l'objet et le modèle qui sera conservé. En gros, le repo "réduit" les objets aux données requises pour les données de persistance.

Un objet métier n'est pas une entité ORM.Il pourrait être d'un point de vue technique, mais d'un dessin pov, un modèle business farcie les autres modèles persistance. Dans de nombreux cas, ils ne sont pas directement compatibles.

La plus grande erreur est de concevoir votre objet métier en fonction des besoins de stockage et de la mentalité. Et contrairement à ce que pensent beaucoup de développeurs, un objectif ORM n’est pas de conserver des objets métier. Son but est de simuler une base de données 'oop' sur un rdbms. Le mappage ORM se situe entre vos objets de base de données et vos tables, et non entre les objets d'application (encore moins lorsqu'il s'agit d'objets métier) et les tables.

88
MikeSW