2010-04-01 13 views
11

Ich habe eine Klasse Person, die eine Reihe von Bücher hat. Im Einzelfall ist eine sortierte oder sortierte Sammlung nicht sinnvoll.Hibernate: ein Set bestellen

Sagen Sie jetzt, dass ich eine Suchseite mit einer Tabelle habe, die den Join von Person und Buch zeigt. Ich möchte in der Lage sein, die Ergebnisse nach Feldern von Person UND Buch zu sortieren und dann eine Liste aus Hibernate zu erhalten und darüber zu iterieren.

Da die Auflistung ein Set ist, ist die Reihenfolge der Bücher verschwunden (PersistentSet of Hibernate umschließt ein HashSet von Büchern, das nicht geordnet ist).

Also, mit diesem Ansatz kann ich nicht Ergebnisse auch nach Buch Felder geordnet haben.

Wenn ich die Auflistung von Set zu List ändere, ist mein Modell semantisch falsch. Es gibt keine Bedeutung für die Ordnung im Modell.

Gibt es einen Ansatz, um die Reihenfolge der Bücher zu halten? Vielleicht gibt es eine Möglichkeit für das PersistentSet, ein LinkedHashSet (welches geordnet ist) zu umbrechen, wobei die Reihenfolge durch meine Suchkriterien definiert wird?

Prost!

Antwort

6

Hibernate unterstützt die Zuordnung einer Sammlung als . In Ihren Zuordnungen müssen Sie im Grunde nur eine order-by Klausel angeben. Werfen Sie einen Blick auf this chapter in the reference manual.

+1

Danke für die Antwort (+1). Ja, das habe ich gesehen. Aber im Beispiel haben sie festgelegt, dass die Reihenfolge auf einem bestimmten Feld liegt. Ich möchte, dass diese Felder über die Kriterien-API festgelegt werden, je nachdem, worauf der Benutzer in der Benutzeroberfläche geklickt hat. –

+1

Sie können auch eine Reihenfolge für Ergebnisse in einer Kriterienabfrage angeben, unabhängig von dem, was Sie im Mapping angeben. http://docs.jboss.org/hibernate/stable/core/reference/en/html/querycriteria.html#querycriteria-order –

+1

Ja, Sie können, aber die Reihenfolge leider durch die Zuordnung (oder @OrderBy) hat Vorrang , wodurch die durch die Kriterien festgelegte Reihenfolge unbrauchbar wird. Oder zumindest kommt es nach der Sortierung der Order-by des Mappings. –

0

nicht sicher, ob ich die Frage richtig habe, aber wenn Sie nur eine Bestellversion Ihrer Liste wollen, können Sie sie einfach mit der Klasse java.util.Collections und einem Komparator sortieren. Vielleicht möchten Sie eine vorübergehende Methode auf Ihrem pojo wie folgt machen:

Schreiben Sie einfach eine Klasse, die Comparator implementiert.

+0

-1: Dies funktioniert für Listen, aber nicht für Mengen und die Liste wird jedes Mal sortiert, wenn der Getter aufgerufen wird. – Kojotak

+0

Sie müssen die Sammlung bei jedem Aufruf sortieren, wenn Sie eine Sammlung verwenden, die ihre Reihenfolge nicht bei jedem Hinzufügen/Entfernen beibehält. –

4

Wie gesagt Markos Fragkakis

unglücklicherauftrags durch in der Mapping (oder @OrderBy) hat Vorrang, das die Reihenfolge durch die Kriterien nutzlos macht eingestellt.

Aber Sie müssen @Order einstellen, wenn Sie das Set bestellt haben wollen.

Sie können immer noch HQL stattdessen verwenden (getestet auf Hibernate 3.3.2.GA), die zunächst in der HQL-Abfrage durch die Reihenfolge bestellen:

@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(); 
     } 
3

Dies ist eine In-Memory-Art, die dafür sorgt, wird von Duplikate in der Join-Tabelle.

@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;