He creado dos entidades JPA (Cliente, InstrumentTraded) usando Hibernate como un proveedor que tiene una relación ManyToMany. Después de dejar Hibernar generar las tablas de MySQL parece que la relación ManyToMany tabla no contiene las claves principales para las dos claves foráneas. Esto permite que los registros duplicados en la de muchos-a-muchos de la tabla, que no es el resultado deseado.

Tablas generadas:

client(id,name)  
instrument_traded(id,name)  
client_instrument_traded(FK client_id, FK instrument_traded_id)

Mesa preferida:

client_instrument_traded(PK,FK client_id, PK,FK instrument_traded_id)

Entidades:

@Entity
public class Client extends AbstractEntity<Integer> {
private static final long serialVersionUID = 1L;
@Basic(optional = false)
@Column(nullable = false, length = 125)
private String name;
@ManyToMany(fetch = FetchType.LAZY)
@JoinTable(joinColumns = {
@JoinColumn}, inverseJoinColumns = {
@JoinColumn(name = "instrument_traded_id")}, uniqueConstraints =
@UniqueConstraint(name = "UK_client_instruments_traded_client_id_instrument_traded_id",
columnNames = {"client_id", "instrument_traded_id"}))
@ForeignKey(name = "FK_client_instruments_traded_client_id",
inverseName = "FK_client_instruments_traded_instrument_traded_id")
private List<InstrumentTraded> instrumentsTraded;
public Client() {
}
public List<InstrumentTraded> getInstrumentsTraded() {
return instrumentsTraded;
}
public void setInstrumentsTraded(List<InstrumentTraded> instrumentsTraded) {
this.instrumentsTraded = instrumentsTraded;
}
...
}
@Entity
@Table(uniqueConstraints = {
@UniqueConstraint(name = "UK_instrument_traded_name", columnNames = {"name"})})
public class InstrumentTraded extends AbstractEntity<Integer> {
private static final long serialVersionUID = 1L;
@Basic(optional = false)
@Column(nullable = false, length = 50)
private String name;
@ManyToMany(mappedBy = "instrumentsTraded", fetch = FetchType.LAZY)
private List<Client> clients;
public InstrumentTraded() {
}
public List<Client> getClients() {
return clients;
}
public void setClients(List<Client> clients) {
this.clients = clients;
}
...
}

Después de hacer algunas investigaciones parece que la única solución es que la asignación de una tabla de combinación con columnas adicionales utilizando @OneToMany @IdClass y una clave principal compuesta de clase cuando no necesito columnas adicionales. Es esta la única solución además del que he incluido en el código de arriba, que es el uso de un @UniqueConstraint con las dos columnas de clave externa en la @ManyToMany asignación? Parece un poco ridículo la cantidad de trabajo necesaria para un escenario como este. Gracias!

  • stackoverflow.com/questions/1212058/…
  • También worths para comprobar si accidentalmente no agregar un registro dos veces, esto me pasó a mí, así que list.add(x); list.add(x); resultados duplicados en las listas.
InformationsquelleAutor dukethrash | 2010-08-13

4 Comentarios

  1. 17

    He tenido un problema similar. Todo lo que hice fue que me cambió el tipo de colección de la Lista para Establecer:

    private List<InstrumentTraded> instrumentsTraded;

    a

    private Set<InstrumentTraded> instrumentsTraded;

    Y de alguna manera ahora Hibernar genera las claves principales para la tabla de combinación.

    • «Todas las grandes cosas son simples…»
    • ¿No es así? O es sólo la de Java Conjunto haciendo su trabajo sobre la memoria?
    • También worths para comprobar si accidentalmente no agregar un registro dos veces, esto me pasó a mí, así que list.add(x); list.add(x); resultados duplicados en las listas.
    • lo que realmente crea una clave principal compuesta! Probado.
  2. 6

    He aquí una manera de resolver el problema:

    Client.java:

     @ManyToMany(fetch = FetchType.EAGER,cascade = CascadeType.ALL)
    @JoinTable(
    joinColumns = {@JoinColumn(name = "client_id")},
    inverseJoinColumns = {@JoinColumn(name = "instrument_traded_id")},
    uniqueConstraints = {@UniqueConstraint(
    columnNames = {"client_id", "instrument_traded_id"})}
    )
    private List<InstrumentTraded> instrumentsTraded;

    Esto es para unidireccional de asignación. Si quieres una relación bidireccional, cambiar la asignación en InstrumentTraded.class a la misma.

  3. 2

    Su asignación parece extraño (en particular, el joinColumn parte de la @JoinTable anotación). Yo esperaría algo como esto:

    @ManyToMany(fetch = FetchType.LAZY)
    @JoinTable(
    joinColumns= 
    @JoinColumn(name="CLIENT_ID", referencedColumnName="ID"), 
    inverseJoinColumns=
    @JoinColumn(name="instrument_traded_id", referencedColumnName="ID"),
    uniqueConstraints=
    @UniqueConstraint(
    name="UK_client_instruments_traded_client_id_instrument_traded_id",
    columnNames = {"client_id", "instrument_traded_id"}
    )
    )
    @ForeignKey(name = "FK_client_instruments_traded_client_id",
    inverseName = "FK_client_instruments_traded_instrument_traded_id")
    private List<InstrumentTraded> instrumentsTraded;

    Pero a menos que usted desea sobrescribir los valores por defecto (y supongo que lo hacen), me acaba de saltar la @JoinTable.

    • Quiero anular los valores predeterminados porque pluralizes la instrument_traded_id (instruments_traded_id). Tengo una costumbre estrategia de asignación de nombres que añade «_id» si «_id» no existe en el extremo de una clave externa. Me puede quitar el [email protected] ¿Tiene usted un ejemplo de trabajo de un ManyToMany crear una clave principal consta de dos claves foráneas en el ManyToMany mesa?
    • tienes un ejemplo de trabajo de un ManyToMany crear una clave principal consta de dos claves foráneas en el ManyToMany tabla? Que es el comportamiento predeterminado si bien anotado. Intenta sin el joinColumn (o con la de arriba)?
    • Sí he probado el tuyo (con la excepción de que referencedColumn es en realidad referencedColumnName) y todavía no la generación de las claves principales. Incluso he añadido el siguiente en InstrumentTraded sólo para ver si eso iba a cambiar nada. @ManyToMany(fetch = FetchType.PEREZOSO, mappedBy = «instrumentsTraded») Lista privada<Cliente> clientes;
    • Yo también lo he probado sin el joinColumn

Dejar respuesta

Please enter your comment!
Please enter your name here