开发者

Does hibernate preserve the order of a LinkedHashSet and if so, how?

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.


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


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.


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.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜