错误:无法为具有多个返回的查询创建TypedQuery

我尝试用java和jpa做函数searchBook。 我有2个class,分别是媒体和书。 本书扩展了媒体。 我将数据保存在不同的表中。 我尝试从下面的查询中选择数据:

TypedQuery query = em.createQuery( "SELECT m.title, b.isbn, b.authors" + " FROM Book b, Media m" + " WHERE b.isbn = :isbn" + " OR lower(m.title) LIKE :title" + " OR b.authors LIKE :authors", Media.class); query.setParameter("isbn", book.getisbn()); query.setParameter("title", "%" + book.getTitle().toLowerCase() + "%"); query.setParameter("authors", "%" + book.getAuthors() + "%"); bookList = query.getResultList(); 

但是我得到了错误:

java.lang.IllegalArgumentException:无法为具有多个返回的查询创建TypedQuery

这是我第一次使用JPA。 我找不到错误。

如果不详细了解MediaBook应该如何建模,我至少会解释为什么你会得到这个例外。

你在做:

 em.createQuery(someJPQL, Media.class); 

这意味着:使用someJPQL创建查询,此查询将返回Media实体的实例。

但是你的JPQL是:

 SELECT m.title, b.isbn, b.authors ... 

因此查询不返回Media类型的实体。 它返回来自两个不同实体的三个字段。 您的JPA引擎无法从这3列中神奇地创建Media实例。 如果查询如下所示,则查询将返回Media的实例:

 select m from Media m ... 

作为一种解决方法,要获取由其他实体属性组成的实体,您可以在查询中创建它,为其提供构造函数。

查询:

 TypedQuery query = em.createQuery("SELECT NEW package_name.Media(m.title, b.isbn, b.authors)" + " FROM Book b, Media m" + " WHERE b.isbn = :isbn" + " OR lower(m.title) LIKE :title" + " OR b.authors LIKE :authors", Media.class); 

实体 :

 public Media(String title, int isbn, String author){ //-- Setting appropriate values } 

我提供了示例,相应地更改了构造函数的数据类型。

如果您使用的是Hibernate版本<4,则可以遇到此错误。

我对v3.5也有同样的问题。 最后我不得不使用简单的Query并手动转换每个参数

请在此处查看其他评论: https : //groups.google.com/forum/#!topic / axonframework / eUd1d4rotMY

@WebUser而不是做

 List companies = getEntityManager().createQuery(sql, EntityIDKey.class).getResultList(); 

尝试这个 :

 List companies = (List)getEntityManager().createQuery(sql).getResultList(); 

适合我。

我……删除

Media.class

的createQuery

因为您在此源中返回更多实体 “SELECT m.title,b.isbn,b.authors”

例:

 TypedQuery query = em.createQuery( "SELECT m.title, b.isbn, b.authors" + " FROM Book b, Media m" + " WHERE b.isbn = :isbn" + " OR lower(m.title) LIKE :title" + " OR b.authors LIKE :authors"); 

如果您仍想使用TypedQuery ,可以将结果类型更改为Object[]

 List results = entityManager .createQuery("SELECT m.title, b.isbn, b.authors ...", Object[].class) .getResultList(); 

每个Object[]代表一行数据。 它包含该行的选定值,按查询中的选择顺序排列。 元素0是标题,元素1是ISBN,元素2是作者。 如果要以有意义的方式使用它们,则可能需要转换这些值。 由于字段值来自两个不同的表,您可以将它们存储在某种容器对象中。

 List mediaList = new ArrayList<>(); for (Object[] row : results) { MediaContainer container = new MediaContainer(); container.setTitle((String) row[0]); container.setIsbn((int) row[1]); container.setAuthors((String) row[2]); mediaList.add(container); }