2010-10-28 38 views
13

Tengo un siguiente problema que debo resolver. El problema central es que quiero agregar una columna adicional en JoinTable para la relación ManyToMany en JPA. En mi caso tengo las siguientes entidades.JPA muchos a muchos con columna adicional

El tema es una entidad simple que tiene muchos RemoteDocument (un RemoteDocument puede ser referido por muchos temas, por lo tanto, debe ser una relación ManyToMany). Además, la entidad RemoteDocument es de solo lectura porque solo puede leerse desde Oracle Materialized View, además, está prohibida cualquier alteración de esta Vista Materializada. Así que quiero guardar el orden de RemoteDocuments relacionado con algún tema. De hecho, yo puedo hacer algo así con entidad adicional:

@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; 
} 

En este caso la entidad adicional TopicToRemoteDocument me ayuda para reemplazar asociación con ManyToMany OneToMany y añadir orden de los campos extra.

Pero yo quiero tener relación ManyToMany pero con columna adicional configurado en tabla de unión

+0

¿Cuál es su proveedor de JPA? JPA 1.0 no tiene una anotación estandarizada para esto, pero su proveedor de JPA podría tener una extensión. –

Respuesta

10

Uso lista en lugar de juego, junto con el @OrderColumn anotación y JPA se encargará automáticamente de la orden:

@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; 
    } 

} 

generada DDL (usando Hibernate y 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

Gracias por su respuesta, es lo que necesito, excepto que estoy usando JPA 1.0 en lugar de JPA 2.0 ... Parece que tengo que migrar a JPA 2.0 – endryha

+4

a) si es la respuesta correcta, debe aceptar b) No creo que haya nada específico sobre JPA 2 en mi respuesta. Debería trabajar con JPA 1 también. Oh, OrderColumn es JPA 2, no lo sabía. –

2

lo haría trate de evitar el uso de List a menos que permita duplicados.

Hay una anotación @OrderColumn que automáticamente hace esto. ¿Lo has probado?

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

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

Una técnica que es útil cuando se crea la entidad clase mapeo muchos-a-muchos es atribuir los identificadores en la clase junto con designación @ManyToOne que hace de este acto de clase como la clase de clave compuesta:

@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; 
    } 
} 

Esto le permite tener la clave primaria compuesta definida dentro de la misma clase sin tener que tener una clase de clave primaria separada. También necesitas hacer que la clase sea serializable.

Cuestiones relacionadas