Ответ 1
Hibernate поддерживает сопоставление коллекции как SortedSet
. В ваших сопоставлениях вам просто нужно указать предложение order-by
. Взгляните на эту главу в справочном руководстве.
У меня есть класс Person, у которого есть набор книг. В конкретном случае не имеет смысла иметь упорядоченную или отсортированную коллекцию.
Скажите, что у меня есть страница поиска со столом, показывающим соединение Person and Book. Я хочу иметь возможность сортировать результаты по полям как Person AND Book, так и получить список из спящего режима и перебирать его.
Поскольку коллекция представляет собой набор, упорядочение книг исчезло (PersistentSet из Hibernate обертывает HashSet книг, который не упорядочен).
Таким образом, при таком подходе я не могу получить результаты, также упорядоченные по полям "Книга".
Если я изменю коллекцию из Set to List, моя модель семантически некорректна. Нет смысла поддерживать порядок в модели.
Есть ли способ сохранить порядок книг? Возможно, существует способ для PersistentSet обернуть LinkedHashSet (который упорядочен), где порядок определяется критериями поиска?
Ура!
Hibernate поддерживает сопоставление коллекции как SortedSet
. В ваших сопоставлениях вам просто нужно указать предложение order-by
. Взгляните на эту главу в справочном руководстве.
Как сказал Маркос Фрагкакис
К сожалению, порядок в сопоставлении (или @OrderBy) имеет приоритет, что делает порядок, заданный критериями бесполезным.
Но вы должны установить @Order, если хотите упорядочить Set.
Вы все равно можете использовать HQL (проверено на hibernate 3.3.2.GA), которые сначала заказывают по порядку в запросе hql:
@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();
}
Это сортировка в памяти, которая позаботится о дубликатах в таблице соединений.
@OneToMany
@JoinTable(name = "person_book", joinColumns = @JoinColumn(name = "person_id"),
inverseJoinColumns = @JoinColumn(name = "book_id"))
@Sort(type = SortType.COMPARATOR, comparator = MyBookComparator.class)
private SortedSet<BookEntity> books;
Не уверен, правильно ли я задал вопрос, но если вы просто хотите версию вашего заказа ordererd, вы можете просто отсортировать ее с помощью класса java.util.Collections и Comparator. Возможно, вы хотите сделать переходный метод на вашем pojo следующим образом:
@Transient
public List<Book> getBooksASC()
{
Collections.sort(this.books, new BookSorter.TitelASCSorter());
return this.books;
}
Просто напишите класс, который реализует Comparator.