2010-10-28 12 views
13

J'ai un problème suivant que j'ai besoin de résoudre. Le problème principal est que je veux ajouter une colonne supplémentaire dans JoinTable pour la relation ManyToMany dans JPA. Dans mon cas, j'ai les entités suivantes. La Sujet est une entité simple qui a beaucoup de RemoteDocument (un RemoteDocument peut être référé par beaucoup de Sujet, donc il devrait être une relation ManyToMany). L'entité RemoteDocument est également en lecture seule car elle peut être lue uniquement à partir d'Oracle Materialized View, toute modification de cette vue matérialisée étant interdite. Donc, je veux stocker l'ordre de RemoteDocuments liés à un sujet. En fait, je peux faire quelque chose comme ça avec entité supplémentaire:JPA beaucoup à beaucoup avec la colonne supplémentaire

@Entity 
public class Topic { 
@Id 
private Long id; 
@Basic 
private String name; 

    @OneToMany 
private Set<TopicToRemoteDocument> association; 
} 

@Entity 
public class RemoteDocument { 
@Id 
private Long id; 
@Basic 
private String description; 
} 

@Entity 
public class TopicToRemoteDocument { 
@OneToOne 
private Topic topic; 
@OneToOne 
private RemoteDocument remoteDocument; 
@Basic 
private Integer order; 
} 

Dans ce cas, l'entité supplémentaire TopicToRemoteDocument me aide à remplacer association ManyToMany avec OneToMany et ajouter ordre de champ supplémentaire.

Mais je veux avoir une relation ManyToMany mais avec colonne supplémentaire configuré dans une table de jointure

+0

Quel est votre fournisseur JPA? JPA 1.0 n'a pas d'annotation normalisée pour cela, mais votre fournisseur JPA pourrait avoir une extension. –

Répondre

10

liste Utiliser au lieu de jeu, ainsi que la prise en charge automatiquement l'annotation @OrderColumn et JPA de l'ordre:

@MappedSuperclass 
public class BaseEntity{ 

    @Id 
    @GeneratedValue(strategy = GenerationType.AUTO) 
    private Long id; 

    public Long getId(){ 
     return id; 
    } 

    public void setId(final Long id){ 
     this.id = id; 
    } 

} 

@Entity 
public class Topic extends BaseEntity{ 

    @ManyToMany(mappedBy = "topics") 
    @OrderColumn 
    private List<Document> documents = new ArrayList<Document>(); 

    public List<Document> getDocuments(){ 
     return documents; 
    } 

    public void setDocuments(final List<Document> documents){ 
     this.documents = documents; 
    } 

} 

@Entity 
public class Document extends BaseEntity{ 

    @ManyToMany 
    @OrderColumn 
    private List<Topic> topics = new ArrayList<Topic>(); 

    public List<Topic> getTopics(){ 
     return topics; 
    } 

    public void setTopics(final List<Topic> topics){ 
     this.topics = topics; 
    } 

} 

DDL générés (en utilisant Mise en veille prolongée et HSQL):

create table Document (
    id bigint generated by default as identity (start with 1), 
    primary key (id) 
); 

create table Document_Topic (
    documents_id bigint not null, 
    topics_id bigint not null, 
    topics_ORDER integer not null, 
    documents_ORDER integer not null, 
    primary key (documents_id, topics_ORDER) 
); 

create table Topic (
    id bigint generated by default as identity (start with 1), 
    primary key (id) 
); 

alter table Document_Topic 
    add constraint FK343B5D0B481100B2 
    foreign key (documents_id) 
    references Document; 

alter table Document_Topic 
    add constraint FK343B5D0B558627D0 
    foreign key (topics_id) 
    references Topic; 
+0

Merci pour votre réponse, c'est exactement ce dont j'ai besoin, sauf que j'utilise JPA 1.0 au lieu de JPA 2.0 ... Donc, il semble que je dois migrer vers le JPA 2.0 – endryha

+4

a) si c'est la bonne réponse, vous devez accepter b) Je ne pense pas qu'il y ait quelque chose de spécifique à JPA 2 dans ma réponse. Devrait travailler avec JPA 1 aussi. Oh, OrderColumn est JPA 2, ne le savais pas. –

2

Je Essayez d'éviter d'utiliser un List sauf si vous autorisez les doublons. Il existe une annotation @OrderColumn qui le fait automatiquement. L'as tu essayé?

@Entity 
public class Topic { 
@Id 
private Long id; 
@Basic 
private String name; 

@OneToMany 
@OrderColumn 
private Set<TopicToRemoteDocument> association; 
} 
0

Une technique qui est utile lors de la création du nombre à plusieurs entités de mapping class est d'attribuer les id dans la classe ainsi que la désignation de @ManyToOne qui rend cet acte de classe comme composite classe clé:

@Entity 
@Table(name = "market_vendor") 
public class MarketVendor implements Serializable 
{ 
    @Id 
    @ManyToOne 
    @JoinColumn(name = "market_id") 
    private Market market; 

    @Id 
    @ManyToOne 
    @JoinColumn(name = "vendor_id") 
    private Vendor vendor; 

    @Basic 
    @Column(name="active") 
    private boolean active; 

    public MarketVendor(Market market, Vendor vendor, boolean active) 
    { 
    this.market = market; 
    this.vendor = vendor; 
    this.active = active; 
    } 
} 

Cela vous permet d'avoir la clé primaire composite définie dans la même classe sans avoir à avoir une classe de clé primaire distincte. Vous devez également rendre la classe sérialisable.