I have a class Person who has a set of Books. It is not meaningful in the particular case to have an ordered or sorted collection.
Say now that I have a search page with a table showing the join of Person and Book. I want to be able to sort the results by fields from both Person AND Book, and then get a List from Hibernate, and iterate over it.
Because the collection is a Set, the ordering of the Books has vanished (PersistentSet of Hibernate wraps a HashSet of Books, which is not ordered).
So, with this approach I cannot have results also ordered by Book fields.
If I change the collection from Set to List, my model is semantically incorrect. There is no meaning for keeping order in the model.
Is there an approach to keep the ordering of Books? Perhaps there is a way for the PersistentSet to wrap a LinkedHashSet (which is ordered), where the order is defined by my search Criteria?
Cheers!
- The sorting occurs in the memory of JVM which running Hibernate, after the data being read from database using java comparator. - The efficiency depends on the size of the collection. - Ordered collection is sorted by specifying the order-by clause for sorting this collection when retrieval.
In hibernate a sorted collection is sorted in memory being Java the responsible of sorting data using compareTo method. Obviously this method is not the best performance-way to sort a collection of elements.
In HQL we perform order by and group by for the given property of entity or associated entities.
Hibernate supports mapping a collection as a SortedSet
. In your mappings you basically just need to specify an order-by
clause. Take a look at this chapter in the reference manual.
Like said Markos Fragkakis
unfortunately order-by in the mapping (or @OrderBy) takes precedence, which makes the ordering set by the Criteria useless.
But you must set @Order if you want to have the Set ordered.
You can still use HQL instead ( tested on hibernate 3.3.2.GA ) who order firstly by the order in the hql query :
@Entity
@Table(name = "Person")
public class Person {
@Id
@Column(name = "ID_PERSON", unique = true, nullable = false, precision = 8, scale = 0)
private Long id;
@OneToMany(fetch = FetchType.LAZY, mappedBy = "person")
@OrderBy
private Set<Book> books = new HashSet<Book>(0);
public Person() {
}
public Long getId() {
return this.id;
}
public void setId(Long id) {
this.id = id;
}
public Set<Book> getBooks() {
return this.books;
}
public void setBooks(Set<Book> books) {
this.books = books;
}
}
/**
* hql Version
*
* Result in :
* order by
* book1_.TITLE asc,
* book1_.ID_BOOK asc
**/
@Override
public Person getFullPerson(Long idPerson) {
StringBuilder hqlQuery = new StringBuilder();
hqlQuery.append("from Person as p ");
hqlQuery.append("left join fetch p.books as book ");
hqlQuery.append("where p.id = :idPerson ");
hqlQuery.append("order by book.title ");
Query query = createQuery(hqlQuery.toString());
query.setLong("idPerson", id);
return uniqueResult(query);
}
/**
* criteria Version // not usable
*
* Result in :
* order by
* book1_.ID_BOOK asc,
* book1_.TITLE asc
**/
@Override
public Person getFullPersonCriteria(Long idPerson) {
Criteria criteria = ...
criteria.add(Restrictions.eq("id", idPerson));
criteria.createAlias("books", "book", CriteriaSpecification.LEFT_JOIN);
criteria.addOrder(Order.asc("book.title"));
return criteria.uniqueResult();
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With