JPA / hibernate tried collection @OrderBy vs @Sort
j'aimerais avoir une collection d'objets enfants (ici chat-chaton exemple) qui sont commandés. Et de garder leur ordre sur l'ajout de nouveaux éléments.
@Entity
public class Cat {
@OneToMany(mappedBy = "cat", cascade = CascadeType.ALL)
@OrderBy("name ASC")
private List<Kitten> kittens;
public void setKittens(List<Kitten> kittens) { this.kittens = kittens; }
public List<Kitten> getKittens() { return kittens; }
}
Quand je fais cat.getKittens.add(newKitten)
la commande par nom sera brisé.
est-il possible de laisser l'hibernation faire le travail de garder la collection toujours commandée? En utilisant le @Sorte hibernate annotation?
@Sort a l'inconvénient qu'il vous force à mettre en œuvre une interface Comparable ...
Ce serait le droit de "pure JPA" façon de le faire? Tout enregistrer et tout recharger?
Est-il logique de combiner @OrderBy et @Sort?
mise à Jour
La Solution jusqu'à présent est de combiner @OrderBy et @Sort. @OrderBy mène à un ORDER BY
clause dans le SQL généré qui est meilleur pour la performance (je suppose que java est "Tri" à nouveau sur l'insertion dans le conteneur trié, mais cela devrait être beaucoup plus rapide parce que les éléments sont déjà triés)
@Sorte avec une mise en œuvre Comparable
l'interface mène à un conteneur toujours trié. Notez que j'utilise maintenant SortedSet
au lieu de List
. Voici le Code mis à jour:
@Entity
public class Cat {
@OneToMany(mappedBy = "cat", cascade = CascadeType.ALL)
@OrderBy("name ASC")
@Sort(type = SortType.NATURAL)
private SortedSet<Kitten> kittens;
public void setKittens(SortedSet<Kitten> kittens) { this.kittens = kittens; }
public SortedSet<Kitten> getKittens() { return kittens; }
}
3 réponses
si vous voulez éviter les annotations non standard, vous pouvez faire kittens
Utilisez quelques triés Collection
mise en œuvre. Cela permettrait de s'assurer que kittens
est toujours dans l'ordre de tri. Quelque chose comme ceci:
@Entity
public class Cat {
@OneToMany(mappedBy = "cat", cascade = CascadeType.ALL)
@OrderBy("name ASC")
private SortedSet<Kitten> kittens = new TreeSet<>();
}
Notez que cette approche exige également Kitten
pour mettre en œuvre Comparable
(alternativement, vous pouvez passer un Comparator
pour votre TreeSet
constructeur). Aussi, je suis en utilisant un Set
parce que je ne suis pas au courant de toute norme triés List
mise en oeuvre et je suppose que Cat
n'a pas de clones dans sa litière =p.
mise à Jour:
Je ne suis pas sûr de savoir à quel point Hibernate est difficile avec ses définitions getter / setter, mais avec EclipseLink j'ai été en mesure d'enlever un setter entièrement et envelopper le List
retourné par mon getter dans un Collections.unmodifiableList(...)
appel. J'ai alors défini des méthodes spéciales pour modifier la collection. Vous pouvez faire la même chose et forcer les appelants à utiliser une méthode add qui insère des éléments dans l'ordre trié. Si Hibernate se plaint de ne pas avoir les getter/setter, vous pourriez peut-être changer le modificateur d'accès? Je suppose qu'il s'agit de savoir jusqu'où vous êtes prêt à aller pour éviter les dépendances non standard.
la dernière version de Hibernate utilise de nouvelles annotations pour accomplir ceci:
@SortNatural
@OrderBy("name ASC")
private SortedSet<Kitten> kittens = new TreeSet<>();
Il y a deux parties à ceci:
@OrderBy
l'annotation spécifie qu'un doit être ajoutée à la requête de la base de données lors de la recherche des enregistrements connexes.@SortNatural
l'annotation suppose queKitten
implémente l'Comparable
l'interface et utilise cette information lors de la construction duTreeSet
instance. Notez que vous pouvez remplacer ce avec l'@SortComparator
annotation, qui vous permet de spécifier unComparator
classe qui sera transmis à l'TreeSet
constructeur.
voir la documentation: https://docs.jboss.org/hibernate/orm/5.2/userguide/html_single/Hibernate_User_Guide.html#collections-sorted-set
@Entity
public class Cat {
@OneToMany(mappedBy = "cat", cascade = CascadeType.ALL)
private Set<Kitten> kittens = new TreeSet<>();
}
Pas besoin de l'écrire
@OrderBy("name ASC")
assurez-vous que la classe chaton implémente l'interface Comparable correctement.