问题
Does hibernate preserve the order of a LinkedHashSet and if so, how? In case this depends on the type of database, I'd like to know this for PostgreSQL.
Background:
I know what a LinkedHashSet is for, and the reason I'm asking this is because I'm logging the names of some functions I execute to a 'logError' table that has a many-to-many relation to some 'functionName' table. I need these functions to remain in the same order as when I executed them, so first I find the corresponding 'functionName' objects, put them in a LinkedHashSet (after each function that failed) and then I persist the 'logError' object.
Now when I get the 'logError' object from the database again, will it still be ordered? And if so, I was curious how this is done by Hibernate.
回答1:
First: I assume you are talking about a relationship between two entities. Something like
@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 does not preserve the order by itself!
If you have a look at the classes used when entity A
is loaded from the database, then the Set
bSet
is of type PersistentSet
, which is a wrapper around another Set
, and this is (in my case) a normal HashSet
. (HashSet
does not preserve the order of its elements.)
Even if Hibernate used List
or LinkedHashSet
, it is still inadvisable to base the implementation on the natural (not guaranteed) database order. For MySQL it is some kind of anti-pattern.
But you can use the @Sort
annotation (org.hibernate.annotations.Sort
) to make your sorting explicit. For example:
@OneToMany(mappedBy = "as")
@Sort(type = SortType.COMPARATOR, comparator = MyBComparator.class);
public SortedSet<C> cs;
@see: Ordering return of Child objects in JPA query
Added by Łukasz Rzeszotarski on 1th Sep 2012:
But we have to remember that using @Sort
annotation causes sorting objects in memory (jvm) and not in sql. Instead we can use @OrderBy
annotation that causes sorting on the sql server side. Both of these annotations have in my (Łukasz Rzeszotarski ) opinion one weakness that set up ordering by default. I (Łukasz Rzeszotarski ) would rather hibernate uses own LinkedHashSet implementation when it 'sees' that order by clause is used.
@see: Hibernate ordering in sql
回答2:
Sets do not have an inherent 'order', nor do database tables - you can apply an order when you query the data, but unless you preserve that order (eg by getting rows one by one and putting them into an ordered container like a linked list) then the returned data will be unordered too.
回答3:
When I need to persist the order of a List of items, I use a Map
and not a 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 }));
In this Java
example, position
is an Integer property of RuleAction
so the order is persisted that way. I guess in C#
this would look rather similar.
来源:https://stackoverflow.com/questions/4243865/does-hibernate-preserve-the-order-of-a-linkedhashset-and-if-so-how