在 hql 查询中使用新构造函数找不到合适的构造函数或无法提取结果集

Using new Constructor in hql query cannot find proper consturctor or could not extract ResultSet

我有实体:

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

然而它导致错误:

Unable to locate appropriate constructor on class [Book]. Expected arguments are: java.util.Collection, java.util.Collection

我尝试调整构造函数以获取对象或集合,并自行转换:

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

但这抱怨:

org.hibernate.exception.SQLGrammarException: could not extract ResultSet

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

感谢您的帮助!

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

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

在你的情况下,你甚至不需要 NEW 因为你可以简单地 select 这本书将由 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;