在HQL查询中使用新的构造方法无法找到合适的构造方法或无法提取ResultSet

时间:2018-09-29 12:27:19

标签: java hibernate persistence

我有实体:

@Entity
public class Author{
    @ManyToMany(cascade = { CascadeType.ALL })
    @JoinTable(
            name = "author_book",
            joinColumns = { @JoinColumn(name = "author_id") },
            inverseJoinColumns = { @JoinColumn(name = "book_id") }
    )
   public List<Book> books;
}

@Entity
public class Book{
   @ManyToMany(mappedBy = "books")
   public List<Author> authors;

   @OneToMany(mappedBy = "book")
   public List<Fact> facts;

   public Book(){}
   public Book(List<Author> authors, List<Fact> facts){
       this.authors = authors;
       this.facts = facts;
   }
}

@Entity class Fact{
   @ManyToOne
   @JoinColumn(name="book_id")
   public Book book;
}

书有更多的作者,作者可以写更多的书。每本书都有更多的相关事实,而每一幕仅属于一本书。

现在我要实现的是基于作者ID接收类型Book的对象。类型Book的对象应包含所有作者和所有事实。

我正在为此使用休眠查询:

List<Book> books = (List<Book>) session.createQuery("Select new Book (books.authors, books.facts ) FROM Author u JOIN u.books books JOIN books.facts WHERE u.id IN :ids ").setParameter("ids", authorId).list();

但是它导致错误:

  

无法在类[Book]上找到适当的构造函数。预期   参数是:java.util.Collection,java.util.Collection

我试图调整构造函数以采用Object或Collection,然后自己进行投射:

   public Book(Object authors,Object facts){
       this.authors = (List<Author>)authors;
       this.facts = (List<Fact>)facts;
   }

但是这抱怨:

  

org.hibernate.exception.SQLGrammarException:无法提取   结果集

然后使用所需数据获取实体的正确方法是什么?它只抱怨关系(例如集合),我在任何地方都找不到解决方案(也没有hql的文档)。

感谢帮助!

1 个答案:

答案 0 :(得分:2)

您不能对实体使用NEW运算符!

这用于DTO(数据传输对象)投影。

在您的情况下,您甚至不需要NEW,因为您只需选择将由Hibernate使用默认构造函数并设置字段的书籍即可。

List<Book> books = 
   (List<Book>) session.createQuery(
   "Select books FROM Author u JOIN u.books books JOIN books.facts WHERE u.id IN :ids ")
   .setParameter("ids", authorId).list();

,如果您想加载收藏集,请使用JOIN FETCH,如:

List<Book> books = 
   (List<Book>) session.createQuery(
   "Select b FROM Book b JOIN FETCH b.authors a JOIN FETCH b.facts f WHERE a.id IN :ids ")
   .setParameter("ids", authorId).list();

重要提示:

Hibernate无法急切地获取两个列表。我建议将列表更改为集:

@ManyToMany(mappedBy = "books")
public Set<Author> authors;

@OneToMany(mappedBy = "book")
public Set<Fact> facts;