2010-09-20 29 views
0

J'ai quatre entités à mapper ensemble, "Association", "Compte", "Transaction" et "TransactionEvent". L'identifiant de l'association est un simple identifiant entier. Compte et Transaction ont chacun des identifiants incorporés consistant en un mappage avec une association et un numéro. TransactionEvent devrait avoir un identifiant incorporé composé d'un compte et d'une association. Maintenant, chacun d'entre eux est mappé à une association, et je veux que ce soit la même association pour un événement de transaction. JPA Les annotations sont utilisées pour le mappage Hibernate, mais je ne peux pas faire fonctionner cela. J'ai essayé de forcer le même nom de colonne pour la clé Association, mais Hibernate se plaint de colonnes répétées.Mapper deux entités à l'aide d'une colonne de clé étrangère partagée en veille prolongée

Est-ce que c'est possible de résoudre, ou je ne pense pas directement?

Voici les classes annotées, mais j'ébarbé getters/setters et des colonnes non-id, les annotations de l'espace de noms javax.persistence:


@Entity 
public class Association implements Serializable { 
    @Id @GeneratedValue(strategy = GenerationType.AUTO) 
    private long id; 
} 

@Embeddable 
public class AccountPK implements Serializable { 
    @ManyToOne(optional=false) 
    private Association association; 

    @Column(nullable=false) 
    private int number; 
} 

@Embeddable 
public class TransactionPK implements Serializable { 
    @ManyToOne 
    private Association association; 

    @GeneratedValue(strategy=GenerationType.AUTO) 
    private long number; 
} 

@Embeddable 
public class AccountEventPK implements Serializable { 
    @ManyToOne(optional=false) 
    @JoinColumns({ 
     @JoinColumn(name="association_id", referencedColumnName="association_id"), 
     @JoinColumn(name="account_number", referencedColumnName="number") 
    }) 
    private Account account; 

    @ManyToOne(optional=false) 
    @JoinColumns({ 
     @JoinColumn(name="association_id", referencedColumnName="association_id"), 
     @JoinColumn(name="transaction_number", referencedColumnName="number") 
    }) 
    private Transaction transaction; 
} 

compte réel, Les entités Transaction et AccountEvent sont sur le formulaire


@Entity 
public class Account implements Serializable { 
     @EmbeddedId 
     private AccountPK id; 
} 
+0

Quoi? Cela n'a aucun sens. Qu'est-ce qu'un Id? Comment pouvez-vous mapper deux choses à une association si elle ne contient qu'un entier? Si vous parlez de pointeurs, java n'en a pas. Le deuxième paragraphe est très confus. Qu'est-ce qu'un identifiant intégré? ... Je pourrais continuer. –

+0

@Leo Peut-être que cela n'a aucun sens pour vous parce que vous ne savez pas Hibernate/JPA @Jon s'il vous plaît montrer vos entités annotées (même si cela ne fonctionne pas). –

+0

@Pascal J'ai ajouté les parties pertinentes du code. J'ai essayé plusieurs variantes d'ajouter "insertable = false, updatable = false" aux annotations JoinTable. – Jon

Répondre

2

Je n'ai pas beaucoup d'expérience pour placer des associations directement dans le composant id incorporé car ceci n'est pas supporté par JPA mais est spécifique à Hibernate.

Comme alternative ma suggestion serait d'utiliser l'approche décrite dans la section Composite Primary Keys de l'Assemblée parlementaire paritaire wikilivre:

(...) JPA 1.0 exige que tous les @Id correspondances soient Basic correspondances, donc si votre identifiant provient d'une clé étrangère colonne par une cartographie OneToOne ou ManyToOne, vous devez également définir une cartographie de base @Id pour la colonne de clé étrangère . La raison de ce est en partie que l'ID doit être un objet simple d'identité et de mise en cache fins, et pour une utilisation dans le IdClass ou l'API EntityManagerfind().

Parce que vous avez maintenant deux correspondances pour la même colonne de clé étrangère, vous devez définir lequel sera écrit à la base de données (il doit être la base un), de sorte que le OneToOne ou ManyToOne doit clé étrangère être défini comme étant en lecture seule. Cela se fait par définissant les attributs JoinColumn insertable et updatable false, ou en utilisant le @PrimaryKeyJoinColumn au lieu du @JoinColumn.

Un effet secondaire d'avoir deux mappings pour la même colonne est que vous maintenant devez conserver les deux en synchronisation. Ceci est généralement effectué à l'aide de la méthode définie pour l'attribut OneToOne également définir la valeur d'attribut de base à l'ID de l'objet cible. Cela peut devenir très compliqué si la cible clé primaire de objet est un GeneratedValue, dans ce cas, vous doit veiller à ce que l'ID de l'objet cible a été affectée avant concernant les deux objets.

(...)

Exemple ManyToOne d'annotation id

... 
@Entity 
@IdClass(PhonePK.class) 
public class Phone { 
    @Id 
    @Column(name="OWNER_ID") 
    private long ownerId; 

    @Id 
    private String type; 

    @ManyToOne 
    @PrimaryKeyJoinColumn(name="OWNER_ID", referencedColumnName="EMP_ID") 
    private Employee owner; 
    ... 

    public void setOwner(Employee owner) { 
     this.owner = owner; 
     this.ownerId = owner.getId(); 
    } 
    ... 
} 

Cela ressemble à être ce que vous cherchez (et peut-être moins compliqué). J'essaierais d'implémenter cette solution (de façon incrémentielle).