我有实体:
@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的文档)。
感谢帮助!
答案 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;