web-dev-qa-db-fra.com

Annotation @OrderColumn dans Hibernate 3.5

J'essaie d'utiliser le @OrderColumn annotation avec Hibernate 3.5

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

Lors de la récupération des données, tout fonctionne bien. Mais je ne peux pas réorganiser les éléments de la liste et enregistrer la nouvelle commande dans la base de données.

25
Piotr Gwiazda

La combinaison de @OneToMany (mappedBy = "...") et @OrderColumn n'est pas prise en charge par Hibernate. Ce problème JIRA suit une demande pour envoyer un message d'erreur plus évident lorsque cette combinaison non valide est utilisée: http://opensource.atlassian.com/projects/hibernate/browse/HHH-539

Je pense que cela n'est pas pris en charge principalement parce que c'est un modèle relationnel étrange. Les annotations ci-dessus indiquent que le côté "un" de la relation détermine comment la relation sera vidée dans la base de données, mais l'ordre/position n'est disponible que du côté "plusieurs" en examinant la liste. Il est plus logique que la partie "plusieurs" soit propriétaire de la relation, car cette partie connaît à la fois l'appartenance et l'ordre des éléments.

Les documents Hibernate Annotations décrivent cette situation en détail:

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

La solution de contournement consiste à supprimer l'attribut "mappedBy", ce qui obligera l'association à utiliser la stratégie de table de jointure par défaut au lieu d'une colonne sur la table cible. Vous pouvez spécifier le nom de la table de jointure à l'aide de l'annotation @JoinTable.

L'effet net de ce changement est que le côté "plusieurs" de la relation détermine maintenant la façon dont la relation est maintenue. Votre code Java Java doit garantir que la liste est correctement mise à jour, car Hibernate ignorera désormais le côté "un" lors du vidage des entités.

Si vous souhaitez toujours avoir le côté "un" accessible en Java, mappez-le avec

@ManyToOne
@JoinColumn(name="...", insertable=false, updatable=false, nullable=false)
29
Peter Centgraf

Faites quelque chose comme ça:

@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);
        }
    }
}
10
Daniel De León

Vous devez essayer de spécifier OrderColumn sur le propriétaire de l'association. Ou dans votre mappage, vous mettez le propriétaire sur l'enfant, le propriétaire doit être le parent (dans une association bidirectionnelle, le propriétaire est celui qui n'a pas le mot-clé mappedBy, ici vous mettez ce mot-clé sur la classe du parent, puis vous signifie que la classe du parent n'est pas le propriétaire)

Dans votre classe enfant, vous devriez avoir le mot-clé mappedBy sur parentCollection. Mais pas sur childrenCollection.
Et dans votre classe parent, vous devriez avoir l'annotation @JoinTable, quelque chose comme ceci:

@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;
3
Nico