web-dev-qa-db-ja.com

名前付きネイティブクエリのIN句にリストを渡すJPA

JPAの名前付きクエリにリストを渡すことができますが、NamedNativeQueryはどうですか?私は多くの方法を試しましたが、それでもリストをNamedNativeQueryに渡すことはできません。 NamedNativeQueryのin句にリストを渡す方法を知っている人はいますか?どうもありがとうございました!

NamedNativeQueryは次のとおりです。

@NamedNativeQuery(
   name="User.findByUserIdList", 
   query="select u.user_id, u.dob, u.name, u.sex, u.address from user u "+
         "where u.user_id in (?userIdList)"
)

そして、それは次のように呼び出されます:

List<Object[]> userList = em.createNamedQuery("User.findByUserIdList").setParameter("userIdList", list).getResultList();

しかし、結果は思ったほどではありません。

System.out.println(userList.size());  //output 1

Object[] user = userList.get(0);
System.out.println(user.length);   //expected 5 but result is 3
System.out.println(user[0]);       //output MDAVERSION which is not a user_id
System.out.println(user[1]);       //output 5
System.out.println(user[2]);       //output 7
28
Li Ho Yin

リストは、JDBCにバインドできないため、ネイティブSQLクエリの有効なパラメーターではありません。リスト内の各引数にパラメーターが必要です。

ここで、u.user_id in(?id1、?id2)

これはJPQLでサポートされますが、SQLではサポートされないため、ネイティブクエリの代わりにJPQLを使用できます。

一部のJPAプロバイダーはこれをサポートする場合があるため、プロバイダーにバグを記録することをお勧めします。

16
James

上記の受け入れられた答えは正しくなく、何日も私を軌道に乗せなかった!!

JPAとHibernateはどちらも、Queryを使用したネイティブクエリのコレクションを受け入れます。

あなたはただする必要があります

String nativeQuery = "Select * from A where name in :names"; //use (:names) for older versions of hibernate
Query q = em.createNativeQuery(nativeQuery);
q.setParameter("names", l);

また、同じことを示唆する回答を参照してください(上記の例をそのうちの1つから選択しました)

  1. リファレンス1
  2. リストをパラメーターとして指定する場合、構文解析が機能するケースについて言及した参考文献2
10
HopeKing

データベース/プロバイダー/ドライバーなどに応じて、実際には、JPAネイティブクエリにバインドされたパラメーターとしてリストを渡すことができます。

たとえば、PostgresとEclipseLinkを使用すると、次のように機能し(trueを返す)、多次元配列と倍精度の配列を取得する方法を示します。 (行う SELECT pg_type.* FROM pg_catalog.pg_type他のタイプの場合;おそらく_、しかしそれを使用する前に剥ぎ取ります。

Array test = entityManager.unwrap(Connection.class).createArrayOf("float8", new Double[][] { { 1.0, 2.5 }, { 4.1, 5.0 } });
Object result = entityManager.createNativeQuery("SELECT ARRAY[[CAST(1.0 as double precision), 2.5],[4.1, 5.0]] = ?").setParameter(1, test).getSingleResult();

キャストがあるため、リテラル配列は数値ではなく倍精度です。

質問のポイントまで-名前付きクエリをどのように、またはできるかはわかりません。多分それは依存すると思います。しかし、配列の場合は次のように動作すると思います。

Array list = entityManager.unwrap(Connection.class).createArrayOf("int8", arrayOfUserIds);
List<Object[]> userList = entityManager.createNativeQuery("select u.* from user u "+
     "where u.user_id = ANY(?)")
     .setParameter(1, list)
     .getResultList();

私はOPと同じスキーマを持っていないので、これを正確に確認していませんが、少なくともPostgresとEclipseLinkでは動作するはずだと思います。

また、キーは次の場所にありました: http://tonaconsulting.com/postgres-and-multi-dimensions-arrays-in-jdbc/

3
Erhannis

Hibernate、JPA 2.1、およびdeltaspikeデータを使用して、IN句を含むクエリのパラメーターとしてリストを渡すことができます。私のクエリは以下です。

@Query(value = "SELECT DISTINCT r.* FROM EVENT AS r JOIN EVENT AS t on r.COR_UUID = t.COR_UUID where " +
        "r.eventType='Creation' and t.eventType = 'Reception' and r.EVENT_UUID in ?1", isNative = true)
public List<EventT> findDeliveredCreatedEvents(List<String> eventIds);
1
IsidIoan

HibernateをプロバイダーとしてJPA2で試してみたところ、hibernateは「IN」のリストの取得をサポートしており、動作するようです。 (少なくとも名前付きクエリでは、名前付きNATIVEクエリと似ていると思います)hibernateが内部的に行うのは、渡されたリストの要素数と同じIN内で動的パラメータを生成することです。

上記の例では

List<Object[]> userList = em.createNamedQuery("User.findByUserIdList").setParameter("userIdList", list).getResultList();

リストに2つの要素がある場合、クエリは次のようになります

select u.user_id, u.dob, u.name, u.sex, u.address from user u "+
         "where u.user_id in (?, ?)

そして、それが3つの要素を持っている場合、それは次のようになります

select u.user_id, u.dob, u.name, u.sex, u.address from user u "+
         "where u.user_id in (?, ?, ?)
1
Ravi Sanwal

現在、HibernateでJPA 2.1を使用しています

また、ネイティブクエリでIN条件を使用します。クエリの例

SELECT ... WHERE table_name.id IN (?1)

ジェームズ

ただし、jpa 2.1 + hibernateを使用すると、文字列値のリストを渡すことができます。私の場合、次のコードは有効です:

    List<String> idList = new ArrayList<>();
    idList.add("344710");
    idList.add("574477");
    idList.add("508290");

    query.setParameter(1, idList);
0
musicccMan

私の場合(EclipseLink、PostGreSQL)、これは動作します:

    ServerSession serverSession = this.entityManager.unwrap(ServerSession.class);
    Accessor accessor = serverSession.getAccessor();
    accessor.reestablishConnection(serverSession);
    BigDecimal result;
    try {
        Array jiraIssues = accessor.getConnection().createArrayOf("numeric", mandayWorkLogQueryModel.getJiraIssues().toArray());
        Query nativeQuery = this.entityManager.createNativeQuery(projectMandayWorkLogQueryProvider.provide(mandayWorkLogQueryModel));
        nativeQuery.setParameter(1,mandayWorkLogQueryModel.getPsymbol());
        nativeQuery.setParameter(2,jiraIssues);
        nativeQuery.setParameter(3,mandayWorkLogQueryModel.getFrom());
        nativeQuery.setParameter(4,mandayWorkLogQueryModel.getTo());
        result = (BigDecimal) nativeQuery.getSingleResult();
    } catch (Exception e) {
        throw new DataAccessException(e);
    }

    return result;

また、クエリでは次のようなエラーが発生するため、IN(?)を使用できません。

原因:org.postgresql.util.PSQLException:エラー:演算子が存在しません:数値=数値[]

「IN(?)」は「= ANY(?)」に交換する必要があります

私のソリューションは、エルハニスのコンセプトに基づいていました。

0