2008-12-22 12 views
5

Me gustaría hacer un mapa de muchos a muchos en Hibernate usando una tabla de enlaces. Tengo dos clases, padres e hijos de la clase, por ejemplo:Cómo asignar la lista de muchos a muchos en Hibernate con una tabla de enlaces

public class Parent{ 

private List<Child> _children; 

//...getters and setters 
} 

Puedo utilizar una tabla de enlace (link_table) con tres columnas link_id, parent_id, y child_id. La base de datos es SQL Server y los tipos de id. Son uniqueidentifier. Por lo tanto, generalmente uso GUID para los campos de Id.

¿Cómo se puede implementar esto usando la etiqueta <list /> si esta es la etiqueta correcta para usar? ¿Conoces alguna buena documentación para lograr esto?

Actualmente estoy obteniendo una excepción de restricción de viaje pero no he podido encontrar ninguna buena documentación o ejemplos de esto.

Creo que un problema principal es: cómo especificar el link_id que se generará automáticamente en la tabla de enlaces.

Respuesta

5

no creo que es posible (o necesario) para añadir una clave principal link_id a la unión mesa. La tabla de unión generalmente constará de las claves principales de las dos tablas participantes.

uso de XML necesitará una sintaxis como esta:

<class name="Parent"> 
    .... 
    <list name="children" table="link_table"> 
    <key column="parent_id"/> 
    <many-to-many column="child_id" 
     class="Children"/> 
    </list> 
    ... 
</class> 

<class name="Child"> 
... 
<list name="parents" inverse="true" table="link_table"> 
    <key column="child_id"/> 
    <many-to-many column="parent_id" 
     class="Parent"/> 
</list> 
... 
</class> 

Aunque me parece mejor utilizar anotaciones.

+5

esto también requiere una columna de índice creo. – Brandon

+0

Requerir es una palabra fuerte. Puede terminar con lo que algunos llamarían un desempeño prohibitivamente pobre sin un índice, pero no puedo imaginar que el índice sea * requerido *. – corsiKa

+2

"columna de índice" es muy diferente de un índice de base de datos en este contexto. – araqnid

0

No estoy seguro de que pueda sacar esto fácilmente de una base de datos existente con datos existentes. Hibernate es usualmente mejor definición de su propio esquema de datos la primera vez que se conecta ...

sólo he tirado fuera de muchos a muchos con anotaciones, pero creo que la documentación de Hibernate ofrece ejemplos basados ​​en XML: link text

7

que hacerlo utilizando anotaciones, específicamente @ManyToMany y @JoinTable:

Hibernate Docs:

@Entity 
public class Employer implements Serializable { 
    @ManyToMany(
     targetEntity=org.hibernate.test.metadata.manytomany.Employee.class, 
     cascade={CascadeType.PERSIST, CascadeType.MERGE} 
    ) 
    @JoinTable(
     name="EMPLOYER_EMPLOYEE", 
     [email protected](name="EMPER_ID"), 
     [email protected](name="EMPEE_ID") 
    ) 
    public Collection getEmployees() { 
     return employees; 
    } 
} 


@Entity 
public class Employee implements Serializable { 
    @ManyToMany(
     cascade = {CascadeType.PERSIST, CascadeType.MERGE}, 
     mappedBy = "employees", 
     targetEntity = Employer.class 
    ) 
    public Collection getEmployers() { 
     return employers; 
    } 
} 
+0

gran respuesta, ayudó mucho –

0

Encontré un muy buen blog en línea que ofrece 2 maneras de agregar campos adicionales a la columna de hibernación mapeada de muchos a muchos. Tradicionalmente esperamos que el mapeo de muchos a muchos brinde una nueva tabla con los FK de las tablas mapeadas. Pero hay formas de modificarlo y agregar más campos/columnas a esta tabla unida.

Esta tabla unida puede contener PK o puede contener algunos campos adicionales sin PK. Ver este blog para la aplicación exacta See Here

Y como por su ejemplo, necesita una PK extra en la mesa, así que declarar un nuevo ParentChildren mesa y declara su clave primaria como linkId. Estoy mostrando solo la clase annoated parentchildren, ya que las anotaciones de mapeo muchos a muchos en clases para padres e hijos se pueden referenciar desde la publicación anterior.

@Entity 
@Table(name = "parent_children") 
public class ParentChildren{ 
    @Id @GeneratedValue 
    private long linkId; 

    @ManyToOne(cascade = CascadeType.ALL) 
    @JoinColumn(name = "parent_id") 
    private Parent parent; 

    @ManyToOne(cascade = CascadeType.ALL) 
    @JoinColumn(name = "children_id) 
    private Children children; 

    // additional fields if you want 
    private boolean activated; 

    //getters and setters 
    } 
} 

Así que esto va a crear una tabla de asignación que ha linkid como clave principal y parent_id y children_id como clave externa. Simplemente tenga en claro por qué quiere un link_id por separado como clave principal y cómo va a usarlo.

Cuestiones relacionadas