我有一个拥有一套书籍的人。在特定情况下,拥有有序或有序集合是没有意义的。
现在说我有一个搜索页面,其中有一个表格显示了Person和Book的连接。我希望能够通过Person和Book中的字段对结果进行排序,然后从Hibernate获取List,并迭代它。
因为集合是一个集合,所以书籍的排序已经消失(Hibernate的PersistentSet包装了一个HashSet of Books,它没有被订购)。
因此,通过这种方法,我无法通过Book字段排序结果。
如果我将集合从Set更改为List,则我的模型在语义上是不正确的。保持模型中的顺序没有任何意义。
是否有办法保持图书的订购?也许PersistentSet有一种方法可以包装一个LinkedHashSet(有序),其中的顺序由我的搜索条件定义?
干杯!
答案 0 :(得分:7)
Hibernate支持将集合映射为SortedSet
。在您的映射中,您基本上只需要指定order-by
子句。看看this chapter in the reference manual。
答案 1 :(得分:4)
像Markos Fragkakis说的那样
遗憾的是,映射(或@OrderBy)中的order-by优先,这使得Criteria设置的排序无用。
但是如果你想让Set有序,你必须设置@Order。
您仍然可以使用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();
}
答案 2 :(得分:3)
这是一种内存中的排序,它将处理连接表中的重复项。
@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;
答案 3 :(得分:0)
不确定我的问题是否正确,但如果您只想要列表的ordererd版本,则可以使用java.util.Collections类和Comparator对其进行排序。也许你想在你的pojo上制作一个瞬态方法:
@Transient
public List<Book> getBooksASC()
{
Collections.sort(this.books, new BookSorter.TitelASCSorter());
return this.books;
}
只需编写一个实现Comparator的类。