2010-11-22 24 views
13

Est-ce que hibernate conserve l'ordre d'un LinkedHashSet et si oui, comment? Dans le cas où cela dépend du type de base de données, j'aimerais le savoir pour PostgreSQL.Est-ce que hibernate conserve l'ordre d'un LinkedHashSet et si oui, comment?

Contexte:

Je sais ce qu'est un LinkedHashSet est pour, et la raison pour laquelle je pose cette question parce que je vous connecter les noms de certaines fonctions, j'exécutons à une table « logError » qui a relation plusieurs-à-plusieurs à une table 'nomFonction'. J'ai besoin que ces fonctions restent dans le même ordre que lorsque je les ai exécutées, donc je trouve d'abord les objets 'functionName' correspondants, les place dans un LinkedHashSet (après chaque fonction qui échoue) et je persiste l'objet 'logError'. Maintenant, quand j'obtiens à nouveau l'objet 'logError' de la base de données, sera-t-il encore commandé? Et si oui, j'étais curieux de savoir comment cela est fait par Hibernate.

+1

Avez-vous essayé d'annoter avec @OrderColumn? (peut-être que c'est une annotation JPA) – willcodejavaforfood

Répondre

13

Premièrement: je suppose que vous parlez d'une relation entre deux entités. Quelque chose comme

@Entity 
public class A { 
@ManyToMany 
    @JoinTable(name = "A_B", joinColumns = { @JoinColumn(name = "A_fk") }, inverseJoinColumns = { @JoinColumn(name = "B_fk") }) 
    private Set<B> bSet = new LinkedHashSet<B>(); 
} 

Hibernate ne conserve pas l'ordre par lui-même!

Si vous avez un regard sur les classes utilisées lorsque l'entité A est chargée à partir de la base de données, le SetbSet est de type PersistentSet, qui est un wrapper autour d'un autre Set, ce qui est (dans mon cas) une normale HashSet. (HashSet ne conserve pas l'ordre de ses éléments.)

Même si Hibernate utilisé List ou LinkedHashSet, il est toujours déconseillé de baser la mise en œuvre de l'ordre de base naturelle (non garantie). Pour MySQL c'est une sorte d'anti-pattern.

Mais vous pouvez utiliser l'annotation @Sort (org.hibernate.annotations.Sort) pour rendre votre tri explicite. Par exemple:

@OneToMany(mappedBy = "as") 
@Sort(type = SortType.COMPARATOR, comparator = MyBComparator.class); 
public SortedSet<C> cs; 

@see: Ordering return of Child objects in JPA query


Ajouté par Łukasz Rzeszotarski le 1 septembre 2012:

Mais il faut se rappeler que l'utilisation de l'annotation @Sort provoque des objets tri memory (jvm) et pas en sql. Au lieu de cela, nous pouvons utiliser l'annotation @OrderBy qui provoque le tri du côté serveur SQL. Ces deux annotations ont dans mon opinion (Łukasz Rzeszotarski) une faiblesse qui a mis en place l'ordre par défaut. Je (Łukasz Rzeszotarski) préférerais hiberner utilise sa propre implémentation LinkedHashSet quand il «voit» que la clause order by est utilisée.

@see: Hibernate ordering in sql

+3

@ Łukasz Rzeszotarski: si vous éditez des postones de nouveau de cette façon, alors faites au moins clair que c'était votre déclaration, et non celle des auteurs originaux! – Ralph

+0

c'est une réponse stupide si vous avez vraiment la carte normale et non la relation d'entité et vous voulez juste préserver l'ordre via 'LinkedHashMap' – Enerccio

+0

@Enerccio: la question est de savoir comment hiberner magasin (ou pas) l'ordre d'un LinkedHashSet, il est pas à propos de vous voulez qu'ils stockent une carte. Si vous pensez que ma réponse est fausse (c'est peut-être le cas) alors s'il vous plaît écrivez une meilleure réponse correcte et je vais supprimer mon et augmenter le vôtre. – Ralph

0

Les ensembles n'ont pas de 'commande' inhérente, pas plus que les tables de base de données - vous pouvez appliquer une commande lorsque vous interrogez les données, mais à moins que vous conserviez cet ordre (par exemple conteneur comme une liste liée) alors les données retournées seront aussi désordonnées.

+1

LinkedHashSet a ordre d'insertion – willcodejavaforfood

0

Quand je dois persister l'ordre d'une liste d'articles, j'utiliser un Map et non un List.

@OneToMany(fetch = FetchType.EAGER, mappedBy = "rule", cascade = CascadeType.ALL) 
@MapKey(name = "position") 
private Map<Integer, RuleAction> actions    = LazyMap.decorate(new LinkedHashMap<>(), FactoryUtils.instantiateFactory(RuleAction.class, new Class[] { Rule.class }, new Object[] { this })); 

Dans cet exemple Java, position est une propriété entière de RuleAction si l'ordre est conservé de cette façon. Je suppose que dans C# cela ressemblerait plutôt.