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; } 
}
31
demandé sur adler 2013-11-09 06:37:13

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.

22
répondu DannyMo 2015-07-28 14:57:01

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:

  1. @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.
  2. @SortNatural l'annotation suppose que Kitten implémente l' Comparable l'interface et utilise cette information lors de la construction du TreeSet instance. Notez que vous pouvez remplacer ce avec l' @SortComparator annotation, qui vous permet de spécifier un Comparator 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

15
répondu mark.monteiro 2017-02-10 23:21:14
@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.

-2
répondu Dax Joshi 2014-11-13 07:48:39