2010-06-02 29 views
21

Estoy tratando de utilizar la anotación @OrderColumn con Hibernate 3,5JPA 2.0 @OrderColumn anotación en Hibernate 3.5

@OneToMany(mappedBy = "parent",fetch=FetchType.EAGER, cascade=CascadeType.ALL) 
@OrderColumn(name = "pos") 
private List<Children> childrenCollection; 

Al recuperar datos, todo funciona bien. Pero no puedo hacer que reordene elementos en la Lista y guarde la nueva orden en la base de datos.

+0

puedo mostrar cómo se re-ordenar su lista y guardar volver a la base de datos ??? –

+0

He intentado crear nuevos ArrayList y parent.setChildrenCollection (newList) He intentado Collections.sort en la lista recuperada. También intenté eliminar elementos nulos de la colección. No pasó nada. Otros cambios en el padre se guardaron en la base de datos, pero no pasó nada con la lista. –

+0

no es Hibernate 3.5 para JPA 1.0, y @OrderColumn es JPA 2.0 ?! –

Respuesta

25

La combinación de @OneToMany (mappedBy = "...") y @OrderColumn no es compatible con Hibernate. Este problema JIRA rastrea una solicitud para arrojar un mensaje de error más obvio cuando se usa esta combinación no válida: http://opensource.atlassian.com/projects/hibernate/browse/HHH-5390

Creo que esto no se admite principalmente porque es un patrón relacional extraño. Las anotaciones anteriores indican que el lado "uno" de la relación determina cómo se va a enjuagar la relación a la base de datos, pero el orden/posición solo está disponible en el lado "muchos" al examinar la Lista. Tiene más sentido para el lado "muchos" poseer la relación, ya que ese lado conoce tanto la membresía como el orden de los elementos.

Los documentos Anotaciones de Hibernate describen esta situación con cierto detalle:

http://docs.jboss.org/hibernate/stable/annotations/reference/en/html_single/#entity-hibspec-collection-extratype-indexbidir

La solución es quitar el atributo "mappedBy", lo que hará que la asociación de usar la estrategia de unión de tablas por defecto en lugar de una columna en la tabla de destino. Puede especificar el nombre de la tabla de unión utilizando la anotación @JoinTable.

El efecto neto de este cambio es que el lado "muchos" de la relación ahora determina cómo persiste la relación. Su código de Java necesita asegurarse de que la Lista se actualice correctamente, ya que Hibernate ahora ignorará el lado "uno" al enjuagar las entidades.

Si aún desea tener el lado "uno" accesible en Java, un mapa con

@ManyToOne 
@JoinColumn(name="...", insertable=false, updatable=false, nullable=false) 
+4

Es curioso que el ejemplo "oficial" para las columnas de índice explícito use exactamente la combinación '@OneToMany (mappedBy =" ... ")' + '@ OrderColumn' (vea el ejemplo 7.8 en http: //docs.jboss.org/hibernate/core/3.6/reference/es-US/html/collections.html # collections-indexed) –

+2

Después de esta respuesta, se acordó que la situación debe ser respaldada de todos modos. Gail Badner: "Estoy de acuerdo con que @OneToMany (mappedBy =" ... ") debería ser compatible." –

+1

¿Hay otro proveedor de JPA (como Eclipselink) que admita '@OneToMany (mappedBy =" ... ")'? – deamon

3

Usted debe tratar de especificar OrderColumn al titular de la asociación. O en su mapeo coloca al propietario del niño, el propietario debe ser el padre (en una asociación bidireccional, el propietario es el que no tiene la palabra clave mappedBy, aquí pone esta palabra clave en la clase del padre, luego te refieres a que la clase del padre no es el propietario)

En tu clase secundaria, debes tener la palabra clave mappedBy en parentCollection. Pero no en la Colección de niños.
Y en su clase padre debe tener la @JoinTable anotación, algo como esto:

@OneToMany(mappedBy = "parent",fetch=FetchType.EAGER, cascade=CascadeType.ALL) 
@OrderColumn(name = "pos") 
@JoinTable(name = "<NAME_OF_YOUR_TABLE>", joinColumns = @JoinColumn(<JOIN_COLUMNS_...>) 
private List<Children> childrenCollection; 
9

hacer algo como esto:

@Entity 
class Parent { 

    @OneToMany 
    @OrderColumn(name = "pos") 
    List<Child> children; 
} 

@Entity 
class Child { 

    @ManyToOne 
    Parent parent; 
    @Column(name = "pos") 
    Integer index; 

    @PrePersist 
    @PreUpdate 
    private void prepareIndex() { 
     if (parent != null) { 
      index = parent.children.indexOf(this); 
     } 
    } 
} 
+2

Creo que en el índice de preparación() debe cambiarse a index = parent.children.indexOf (this); if (index == -1) index = parent.children.size(); – cn123h