2010-03-09 5 views
4

En d'autres termes: comment modéliser/mapper une classe/table enfant fortement réutilisée vers plusieurs entités parentes?Hibernate meilleure approche pour une classe Java et plusieurs tables?

J'ai plusieurs types d'entités, chacune étant dans persista sa propre table:

classe A -> Tableau A classe B -> tableau B ....

Maintenant, je dois faire chacune de ces classes est le parent d'une collection enfant unidirectionnelle 1: M. La collection est un historique des approbations que l'entité a acquises au fil du temps. La classe de domaine enfant est appelée "ApprovalItem". La classe d'approbation est exactement la même pour tous les types de parents.

Quelle est la meilleure façon de mapper cela? Si je crée une seule table pour contenir tous les ApprovalItems, alors je ne peux pas appliquer une relation FK au PK de l'entité et/ou il me reste une mauvaise conception de base de données. En revanche, je pourrais créer une table ApprovalIems pour chaque type d'entité (par exemple, A_ApprovalItems, B_ApprovalItems, etc.)

D'autre part, je pourrais créer une table ApprovalIems pour chaque type d'entité (par exemple, A_ApprovalItems, B_ApprovalItems, etc.). Cela semble être un bon schéma du côté de la base de données, mais il semble que je doive créer des classes de domaine séparées en Java pour chaque approbation d'entité (par exemple, classe AAprrovalItem, classe BApprovalItem, etc.). Cela semble beaucoup de tracas et de complexité pour créer autant de nouvelles classes en Java qui ne font rien d'autre que de me permettre de mettre différentes annotations de mapping JPA.

Existe-t-il une technique de mappage dans Hibernate qui me permettra d'avoir une classe dans la carte Java à plusieurs tables différentes en fonction de qui est le propriétaire parent de la collection?

Répondre

3

Je pourrais créer une table ApprovalItem pour chaque type d'entité (par exemple, A_ApprovalItem, B_ApprovalItem, etc.). Cela semble être un bon schéma du côté de la base de données

Mais

Il semble que je dois créer un cours de domaine distincts en Java pour approbation de chaque entité (par exemple AAprrovalItem de classe, classe BApprovalItem, etc. .).

Vous n'en avez pas besoin. Vous pouvez créer une seule classe ApprovalItem et créer une relation @OneToMany entre vos classes parentes et votre ApprovalItem. Hibernate prend soin de créer une table liée pour chaque relation.

@Entity 
public class ClassA { 

    @Id 
    @GeneratedValue 
    private Integer id; 

    // Hibernate will create CLASSA_APPROVALITEM to link both class 
    @OneToMany 
    private List<ApprovalItem> approvalItemList; 

} 

@Entity 
public class ClassB { 

    @Id 
    @GeneratedValue 
    private Integer id; 

    // Hibernate will create CLASSB_APPROVALITEM to link both class 
    @OneToMany 
    private List<ApprovalItem> approvalItemList; 

} 

Et votre classe ApprovalItem

@Entity 
public class ApprovalItem { 

    @Id 
    @GeneratedValue 
    private Integer id; 

    // Nothing else 

} 

Mais Voyons voir ce que Java Persistence avec livre parle Hibernate à ce sujet

Vous pouvez avoir références partagées aux objets d'appel d'offres. Comme suggéré précédemment, un utilisateur peut avoir une collection de références aux instances d'enchères qu'il a créées. Vous ne pouvez pas supprimer un élément et toutes ses enchères sans supprimer ces références en premier. Vous pouvez obtenir une exception si vous tentez de valider cette transaction, car une contrainte de clé étrangère peut être enfreinte.

Gardez cela à l'esprit lorsque vous traitez des références partagées.

Afin de voir comment le schéma cible ressemble, vous pouvez utiliser les éléments suivants

AnnotationConfiguration configuration = new AnnotationConfiguration(); 

configuration 
    .addAnnotatedClass(ClassA.class) 
    .addAnnotatedClass(ClassB.class) 
    .addAnnotatedClass(ApprovalItem.class) 
    .setProperty(Environment.USER, <TYPE_YOUR_USER>) 
    .setProperty(Environment.PASS, <TYPE_YOUR_PASSWORD>) 
    .setProperty(Environment.URL, <TYPE_YOUR_URL>) 
    .setProperty(Environment.DIALECT, <TYPE_YOUR_DIALECT>) 
    .setProperty(Environment.DRIVER, <TYPE_YOUR_DRIVER>); 

SchemaExport schema = new SchemaExport(configuration); 
schema.setOutputFile("schema.sql"); 

schema.create(<DO_YOU_WANT_TO_PRINT_TO_THE_CONSOLE>, <DO_YOU_WANT_TO_EXPORT_THE_SCRIPT_TO_THE_DATABASE>); 

Il va générer un fichier appelé schema.sql, qui contient votre schéma cible

concernant,

+0

Cela semble parfait du côté Java, mais pouvez-vous préciser à quoi ressemble le schéma dans la base de données? Je suppose qu'il existe une table de jointure entre les tables d'entités et la table approvalitem - est-ce exact? – HDave

+0

@HDave Oui, nous avons trois classes: ClassA, ClassB et ApprovalItem; et cinq tables: CLASSA, CLASSB, APPROVALITEM, CLASSA_APPROVALITEM (Il prend soin de lier les instances ClassA et ApprovalItem) CLASSB_APPROVALITEM (Il prend soin de lier les instances ClassB et ApprovalItem) –

+0

100% awesome goodness .... merci. – HDave

2

Chapter 8. Inheritance Mapping de Hibernate La documentation pourrait aider.

Sinon, je ne vois pas de problème à avoir plusieurs classes dérivées ApprovalItem qui "ne font rien", comme vous le dites, car cela différencie l'approbation, c'est comme avoir un type d'approbation. En voyant votre modèle comme tel, je recommanderais d'utiliser plusieurs classes, même si elles héritent uniquement de votre classe ApprovalItem de base. Est-ce que j'ai bien compris votre question ou est-ce que je manque quelque chose d'autre de plus subtile?

+0

Je pense que vous avez parfaitement compris le problème. J'essayais juste d'éviter la multiplicité des classes car j'ai 12 de ces entités et 3 différentes collections d'enfants. C'est 36 classes de domaine qui ne font rien d'autre que de tenir différentes annotations JPA. Juste déteste l'idée de la persistance de polluer ma représentation du domaine! Mais votre suggestion est ce que je ferai si rien ne se passe mieux ... merci. – HDave

+0

Je comprends ce que vous voulez dire et comprends votre argumentation. Malgré, il ne pollue pas votre modèle de domaine, il ne fait que le préciser. Peut-être était-ce votre modèle qui n'était pas suffisant pour vos besoins actuels. Quoi qu'il en soit, heureux d'avoir aidé. =) –