2011-12-23 11 views
12

Tengo una pregunta similar a @ManyToMany without join table (legacy database) con un problema adicional.Asignación de una base de datos de solo lectura con una relación de varios a varios sin una tabla de unión

que tienen dos mesas A y B

  • A con una llave múltiple columna primaria (ID y ID2)
  • B con una clave de múltiples columna primaria (ID y ID3)

Una fila en A puede hacer referencia a varias filas en B (B.ID = A.ID) y una fila en B se puede hacer referencia por varias filas en A.

EDIT: la base de datos es una base de datos heredada de solo lectura que no puedo cambiar. No necesito mapear las relaciones con JPA (podría hacerlo en mi lógica de programa con selecciones adicionales) pero sería bueno.

Básicamente es una relación de muchos a muchos sin una tabla de unión. Dado que, en cuanto a la pregunta vinculada, solo tengo que leer las tablas, probé con dos relaciones uno a muchos en ambas clases.

El problema adicional que tengo es que ambos ID s utilizados para la unión no son la clave principal.

tengo las siguientes clases:

@Entity 
@Table(name = "A") 
@IdClass(PrimaryKeysA.class) 
public class A { 

    @Id 
    @Column(name = "ID", insertable = false, updatable = false, columnDefinition = "char") 
    private String id; 

    @Id 
    @Column(name = "ID2", insertable = false, updatable = false) 
    private int id2; 

    @OneToMany(cascade = CascadeType.ALL) 
    @JoinColumn(name = "ID", columnDefinition = "char", referencedColumnName = "ID") 
    private Set<B> setOfBs; 

} 

@Entity 
@Table(name = "B") 
@IdClass(PrimaryKeysB.class) 
public class B { 

    @Id 
    @Column(name = "ID", insertable = false, updatable = false, columnDefinition = "char") 
    private String id; 

    @Id 
    @Column(name = "ID3", insertable = false, updatable = false) 
    private int id3; 

    @OneToMany(cascade = CascadeType.ALL) 
    @JoinColumn(name = "ID", columnDefinition = "char", referencedColumnName = "ID") 
    private Set<A> setOfAs; 

} 

Hibernate genera el siguiente error:

Exception while preparing the app : referencedColumnNames(ID) of package.B referencing package.A not mapped to a single property 

Realmente no me sale el mensaje: B.id hace referencia a una sola propiedad en A (A.id) .

EDIT: conforme a lo solicitado:

public class PrimaryKeysA implements Serializable { 

private static final long serialVersionUID = 1L; 

private int id1; 
private int id2; 

    // getters/setters/equals/hashcode 

} 

PrimaryKeysB es similar con ID3 en lugar de ID2. Ambas clases A y B son ejemplos simplificados (anónimos).

+1

Realmente no veo cómo puede tener muchos con muchos en estas tablas. A.ID hace referencia a B.ID y B.ID es la clave principal de B. Entonces, una A determinada solo puede hacer referencia a una B. Simplemente tienes una asociación ManyToOne de la A a la B. –

+0

Ooops, siento que tengo lo mismo en A como en B. Editaré la pregunta (traté de generar un ejemplo simplificado yendo también ahora) – Matteo

+0

Esta no es una asociación de muchos a muchos entre dos tablas ... ¿Por qué estás usando dos identificadores en cada mesa? ¿Tiene la capacidad de cambiar este esquema en una forma más estándar o se trata de una base de datos heredada? Si no es una base de datos heredada, ¿cuál es el motivo por el que no utiliza una tabla de combinación si desea una asociación de muchos a muchos? –

Respuesta

4

Se puede crear una vista que actuaría como tabla de unión:

CREATE VIEW AJOINB AS 
SELECT A.ID as AID, A.ID2 as AID2, B.ID as BID, B.ID3 as BID3 
FROM A JOIN B ON A.ID = B.ID 

Y luego asignarla en JPA como ManyToMany con AJOINB como tabla de unión.

Si A.ID2 y B.ID3 eran únicos por sí mismos, ni siquiera necesitaría asignar A.ID y B.ID en sus beans JPA.

+0

Dado que el DB es de solo lectura, tendría que crear un nuevo DB con una copia de todas las tablas más la vista adicional (ya que no creo que pueda definir dos entidades en un DB y la tabla de unión en otro). Al tener que usar una base de datos adicional, trataría de refactorizar los datos de una mejor manera. Pero podría valer la pena ... – Matteo

+0

Depende de su base de datos. En Oracle y SQL Server puede usar alias de tabla. Y la creación de una vista de esquemas es posible incluso en MySQL. – greyfairer

+0

Sí, la creación de la vista en otro esquema no es un problema. Me temo (no controlé) que definir una entidad en un esquema con la tabla de unión en otro no funcionará. Pero tendré que trabajar con un enlace de DB ya que el DB (no solo el esquema) es de solo lectura: no tengo otro acceso. – Matteo

2

¿Puede compartir algunos registros de muestra de sus tablas?

El problema es muy claro. Para cualquier relación uno-muchos, en el lado "uno", debe haber solo un registro que pueda ser identificado de manera única. Aquí, creo, dado que id no es único, hay múltiples entradas.

Puede intentar utilizar @JoinColumns y agregar ambas columnas para identificar de forma única a la entidad en el lado "uno".

@OneToMany 
@JoinColumns({ 
    @JoinColumn(name="yourID1", referencedColumnName="yourID1"), 
    @JoinColumn(name="yourid2", referencedColumnName="yourid2") 
}) 

Supongo que tiene los siguientes datos.

cuadro A:

id2 c1   id 
100 content1 1000 
101 content2 1001 

la tabla B:

id3 s1   id 
100 content1 1000 
101 content2 1000 
102 content3 1001 
103 content4 1001 

Aquí ID2 e ID3 son únicos. A.id es único pero b.id no lo es; un escenario típico de OneToMany.

Si Mapa de A a B utilizando A.id y B.id, entonces este se convierte en-uno a muchos, donde A (100) puede referirse a B (100, 101) como el ID es 1000

Esto funcionará bien, creo. Pero si tiene que mapear de B a A usando las mismas columnas (como se indica en la pregunta), no funcionará, ya que un lado (B) tiene duplicados.

¿Estoy entendiendo su pregunta correctamente?

+0

Por cierto, no sé cómo agregar esto como comentario sin publicar algo como respuesta. ¿Alguien me puede ayudar? –

+0

Hibernate se queja por muchos lados. Tengo un A.id1 que hace referencia a B.id1. B.id1 no es único (uno-a-muchos). Hibernate se queja diciéndome que B.id1 es parte de una clave principal: pero a quién le importa. Para cada A.id1 tengo más B.id1s. Si B.id1 también es ** parte ** de la clave primaria de B, no debería ser relevante. Las tablas solo están relacionadas a través de id1 (id2 no existe en B). – Matteo

+0

Necesita una reputación de 50 para poder comentar – Matteo

Cuestiones relacionadas