代码之家  ›  专栏  ›  技术社区  ›  pkainulainen

使用请求实体的子实体的信息对hibernate条件查询的结果排序

  •  4
  • pkainulainen  · 技术社区  · 14 年前

    我有两个实体人和书。只有一个特定图书的实例存储到系统中(添加图书时,应用程序将在向数据库添加新行之前检查是否已找到该图书)。相关实体源代码如下:

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

    我的问题是我想找一些人,他们拥有一个特定的人拥有的一些书。返回的人员列表应使用以下逻辑进行排序:拥有大多数相同书籍的人员应位于列表的第一位,列表的第二位人员拥有的书籍数量不应超过第一位人员,而应超过第三位人员。执行此查询的方法的代码添加如下:

    @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 
    

    我一直在尝试如何将其转换为条件查询。我一直在尝试使用投影,但似乎无法将结果映射回Person对象。

    2 回复  |  直到 14 年前
        2
  •  1
  •   pkainulainen    14 年前

    我终于设法解决了这个问题。以下方法按预期工作:

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

    我还通过添加名为 相似帐簿计数 ,这在某些情况下可能有用。