在 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;
我有实体:
@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;