2 votes

Objets enfants dans CouchDB avec Java

UPDATE : Merci funql/Kim. Je comprends votre point de vue. Si vous me permettez une question complémentaire, existe-t-il un moyen de réaliser la persistance des objets (comme suggéré par Funql pour Mongo) à l'aide de Couch ? D'après ce que j'ai compris avant de commencer ce projet, c'est l'un des avantages des bases de données NoSQL - vous n'avez pas besoin de vous soucier des couches DAO, vous pouvez pratiquement déverser un objet dans un document et l'extraire au besoin, sans problème, laissant la définition du schéma être entièrement impliquée par la définition de votre classe, et je ne vois pas de raison fondamentale pour laquelle cela fonctionnerait dans MongoDB mais pas dans CouchDB ?


J'utilise CouchDB pour la première fois dans une application d'entreprise et j'ai l'impression qu'il me manque quelque chose de fondamental dans la mentalité NoSQL.

Supposons que vous ayez les classes Java suivantes :

public class Customer { ... }

public abstract class Product { ... } // could just as well be an interface
public class ProductA extends Product { ... };
public class ProductB extends Product { ... };

public class Sale {
  private String transactionId;
  private Customer customer;
  private List<Product> items;
  // ...
}

Lorsque je stocke une vente dans une base de données Couch (ou toute autre base de données de stockage de documents), je me retrouve avec un seul document contenant l'intégralité de la vente, ce qui est ce que je veux. Cependant, je rencontre un problème dès que je commence à essayer de stocker/récupérer des classes abstraites ou des classes qui implémentent une interface. L'enregistrement de ma vente ressemble généralement à quelque chose comme ceci (simplifié) :

{
   "transactionId": "12345",
   "customer": { "name": "Joe Soap" },
   "items": [
       {
           "name": "Coke",
           "price": 12.99,
           "qty": 1
       },
       {
           "name": "Minced meat",
           "weight": 1.23,
           "price": 49.99
       }
   ]
}

Maintenant, la récupération de ces données est simple dans le cas du client - je peux utiliser un sérialiseur/désérialiseur personnalisé et utiliser la réflexion pour dire que Sale.customer est une instance de Customer , instanciez une instance et définissez ses champs à partir des données JSON.

Cependant, cela devient beaucoup plus délicat avec le items car je n'ai aucune idée de la sous-classe de Product à instancier pour chaque élément de la liste (et je ne peux pas initialiser une instance d'une classe abstraite ou d'une interface).

J'ai essayé de contourner ce problème en stockant le nom complet de la classe avec les données (par exemple chaque Product L'enregistrement contiendrait un @class pour indiquer quel type d'objet a été sérialisé, et donc quel type doit être initialisé lors de la désérialisation), mais cela signifie que je me crée un problème si jamais, par exemple, je déplace cette classe dans un autre paquetage (comme le champ @class sera alors invalide). Bien que cela puisse être atténué avec la migration scripts (ou d'autres approches), j'ai l'impression de passer à côté d'un point fondamental et de le contourner.

Quelqu'un peut me dire ce que je fais de mal ? Existe-t-il une approche plus élégante qui me permettrait de ne pas avoir à manipuler autant le code de sérialisation, puisque je crois comprendre que les bases de données NoSQL sont censées réduire le temps que les développeurs doivent passer à écrire du code de persistance ?

Pour ce que ça vaut, j'ai essayé d'utiliser Ektorp et LightCouch, et j'ai eu des problèmes similaires avec les deux.

2voto

funql.org Points 41

Il s'agit d'un problème typique de la cartographie objet-relationnel. Il ne s'agit pas d'un problème limité aux bases de données documentaires.

Vous pouvez choisir entre trois approches :

  1. Maintenir une correspondance entre l'identifiant de la classe et la classe réelle dans la base de données.
  2. Maintenez ce mappage dans l'application
  3. Ne pas mapper. mais mettre à jour les documents dans la base de données lorsqu'une classe est déplacée.

D'après mon expérience, la plupart des gens optent pour l'alternative 2, car ils veulent garder la base de données indépendante des détails de l'application (classes/packages).

Dans une application antérieure, où j'avais le même problème, j'ai simplement maintenu une table de correspondance pour les classes qui ont été déplacées. C'est facile à faire.

Si vous ne souhaitez pas manipuler le code de sérialisation, vous pouvez utiliser l'un des frameworks de persistance d'objets disponibles pour MongoDB.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X