4

PersonとBookの2つのエンティティがあります。特定の本のインスタンスが1つだけシステムに保存されます(本が追加されると、アプリケーションは、データベースに新しい行を追加する前に、その本がすでに見つかっているかどうかを確認します)。エンティティの関連するソースコードは以下にあります:

@Entity
@Table(name="persons")
@SequenceGenerator(name="id_sequence", sequenceName="hibernate_sequence")
public class Person extends BaseModel
{
    @Id
    @Column(name = "id")
    @GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "id_sequence")
    private Long id = null;

    @ManyToMany(targetEntity=Book.class)
    @JoinTable(name="persons_books", joinColumns = @JoinColumn( name="person_id"), inverseJoinColumns = @JoinColumn( name="book_id"))
    private List<Book> ownedBooks = new ArrayList<Book>();
}

@Entity
@Table(name="books")
@SequenceGenerator(name="id_sequence", sequenceName="hibernate_sequence")
public class Book extends BaseModel
{
    @Id
    @Column(name = "id")
    @GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "id_sequence")
    private Long id = null;

    @Column(name="name")
    private String name = null;
}

私の問題は、特定の人が所有する本のいくつかを所有している人を見つけたいということです。返される人のリストは、次のロジックを使用して並べ替える必要があります。同じ本のほとんどを所有している人はリストの最初にあり、リストの2番目の人は最初の人ほど多くの本を所有していません。第三者。このクエリを実行するメソッドのコードを以下に追加します。

@Override
public List<Person> searchPersonsWithSimilarBooks(Long[] bookIds) {
    Criteria similarPersonCriteria = this.getSession().createCriteria(Person.class);
    similarPersonCriteria.add(Restrictions.in("ownedBooks.id", bookIds));

    //How to set the ordering?
    similarPersonCriteria.addOrder(null);

    return similarPersonCriteria.list();
}

私の質問は、Hibernateを使用してこれを実行できるかどうかです。もしそうなら、それはどのように行うことができますか?コンパレータを実装できることはわかっていますが、この問題を解決するにはHibernateを使用したいと思います。

SQLを使用する場合、次のSQLクエリを使用して必要な結果を得ることができます。

select p.name, count(p.name) as bookCount from persons p, books b, person_book pb
where pb.person_id = p.id and pb.book_id = b.id and b.id in (1,2,3,4,5,6) group by
name order by bookCount desc 

私はこれをCriteriaクエリに変換する方法を見つけようとしてきました。Projectionsを使用しようとしていますが、結果をPersonオブジェクトにマップして戻すことができないようです。

4

2 に答える 2

2

これは役に立ちますか?

http://docs.jboss.org/hibernate/core/3.3/reference/en/html/querycriteria.html#querycriteria-ordering

于 2010-04-10T20:00:57.340 に答える
1

私はついにこの問題を解決することができました。次の方法は期待どおりに機能します。

@Override
public List<Person> searchPersonsWithSimilarBooks(Long[] bookIds) {
    Criteria similarPersonCriteria = this.getSession().createCriteria(Person.class, "p");

    Criteria bookCriteria = similarPersonCriteria.createCriteria("ownedBooks", "b");
    bookCriteria.add(Restrictions.in("b.id", bookIds));

    similarPersonCriteria.setProjection(Projections.projectionList()
            .add(Projections.groupProperty("p.id"), "id")
            .add(Projections.rowCount(), "similarBookCount"));

    similarPersonCriteria.addOrder(Order.desc("similarBookCount"));
    similarPersonCriteria.setResultTransformer(new AliasToBeanResultTransformer(Person.class));

    return similarPersonCriteria.list();
}

また、 similarBookCountという一時的なプロパティを追加して、personクラスを更新しました。これは、状況によっては便利です。

于 2010-04-11T19:37:52.160 に答える