web-dev-qa-db-ja.com

エラー:複数の戻り値を持つクエリのTypedQueryを作成できません

Javaおよびjpaを使用して関数searchBookを実行しようとします。MediaとBookの2つのクラスがあります。BookはMediaを拡張します。そして、データを別のテーブルに保持します。以下のクエリからのデータ:

TypedQuery<Media> 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を使用するのはこれが初めてです。私は間違いを見つけることができません。

23
user1412944

MediaBookをモデル化する方法の詳細については説明しませんが、この例外が発生する理由を少なくとも説明します。

あなたはやっている:

em.createQuery(someJPQL, Media.class);

つまり、someJPQLを使用してクエリを作成すると、このクエリはMediaエンティティのインスタンスを返します。

しかし、あなたのJPQLは:

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

したがって、クエリはタイプがMediaのエンティティを返しません。 2つの異なるエンティティから3つのフィールドを返します。 JPAエンジンがこれらの3つの列からMediaのインスタンスを魔法のように作成できる方法はありません。クエリが次のような場合、Mediaのインスタンスを返します。

select m from Media m ...
36
JB Nizet

回避策として、他のエンティティ属性で構成されたエンティティを取得するには、クエリ内でエンティティを作成し、そのコンストラクタを提供します。

クエリ:

TypedQuery<Media> 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
}

私はサンプルを提供し、それに応じてコンストラクターのデータ型を変更します。

50
Nayan Wadekar

それでもTypedQueryを使用したい場合は、結果のタイプをObject[]に変更できます。

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

Listの各Object[]は、データの行を表します。これには、その行で選択された値が、クエリで選択された順序で含まれています。要素0はタイトル、要素1はISBN、要素2は作成者です。意味のある方法で使用したい場合は、これらの値をキャストする必要があるでしょう。フィールド値は2つの異なるテーブルから取得されるので、それらをある種のコンテナーオブジェクトに格納できます。

List<MediaContainer> 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);
}
1
David DeMar

私は...削除

Media.class

createQuery

より多くを返すためEntitiesこのソースで"SELECT m.title、b.isbn、b.authors"

例:

TypedQuery<Media> 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");
0
acacio.martins

代わりに@WebUser

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

これを試して :

List<EntityIDKey> companies =
(List<EntityIDKey>)getEntityManager().createQuery(sql).getResultList();

私のために働く。

0
dubem uzuegbu

hibernateバージョン<4を使用している場合は、このバグに対応できます。

V3.5でも同じ問題が発生します。最後に、単純なクエリを使用して、各パラメーターを手動でキャストする必要がありました

ここの他のコメントを参照してください: https://groups.google.com/forum/#!topic/axonframework/eUd1d4rotMY

0