50

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
4

13 に答える 13

41

上記の受け入れられた答えは正しくなく、私を何日も軌道から外してしまいました!!

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. パラメータとしてリストを与えるどのケースのparanthesisが機能するかについて言及した参考文献2

*これらの参照はjpqlクエリに関するものですが、コレクションの使用法はネイティブクエリでも機能することに注意してください。

于 2018-06-11T08:56:16.447 に答える
23

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

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

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

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

于 2011-06-08T13:02:35.413 に答える
9

データベース/プロバイダー/ドライバーなどによっては、実際には、リストをバインドされたパラメーターとして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();

キャストが存在するため、リテラル配列は数値ではなくdoubleです。

質問の要点をもっと詳しく説明します。名前付きクエリを実行する方法や実行できるかどうかはわかりません。多分それは状況次第だと思います。しかし、私は以下がアレイのもののために働くと思います。

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/

于 2018-03-08T21:34:28.487 に答える
7

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);
于 2018-06-12T20:17:38.843 に答える
2

現在、HibernateでJPA2.1を使用しています

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

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

Jamesが説明した制限のため、「id_1、id_2、id_3」のような文字列を渡すことができないことに気づきました。

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

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

    query.setParameter(1, idList);
于 2018-06-29T14:17:09.407 に答える
2

私の場合(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:エラー:演算子が存在しません:numeric =numeric []

'IN(?)'は'= ANY(?)'にスワップする必要があります

私のソリューションはErhannisのコンセプトに基づいていました。

于 2019-07-27T08:26:57.910 に答える
1

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 (?, ?, ?)
于 2013-03-04T22:20:47.013 に答える
1

jpaでは、それは私のために働きました

@Query(nativeQuery =true,value = "SELECT * FROM Employee as e WHERE e.employeeName IN (:names)")  
List<Employee> findByEmployeeName(@Param("names") List<String> names);
于 2021-01-14T02:02:02.903 に答える
1

これを行う必要があります:

String userIds ="1,2,3,4,5"; List<String> userIdList= Stream.of(userIds.split(",")).collect(Collectors.toList());

次に、次のように、クエリ内でlikeパラメータを渡します。

@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)")

于 2021-02-03T23:35:55.243 に答える
0

標準のJPAでは不可能です。Hibernateは独自の方法setParameterList()を提供しますが、Hibernateセッションでのみ機能し、JPAでは使用できませんEntityManager

私はHibernateの次の回避策を考え出しました。これは理想的ではありませんが、ほぼ標準のJPAコードであり、いくつかの優れたプロパティがあります。

orm.xml手始めに、名前付きネイティブクエリをファイル内で適切に分離しておくことができます。

<named-native-query name="Item.FIND_BY_COLORS" result-class="com.example.Item">
    <query>
        SELECT i.*
        FROM item i
        WHERE i.color IN ('blue',':colors')
        AND i.shape = :shape
    </query>
</named-native-query>

プレースホルダーは一重引用符で囲まれているため、有効なネイティブJPAクエリです。パラメータリストを設定せずに実行され、他の一致するカラーパラメータが設定されている場合でも正しい結果を返します。

DAOまたはリポジトリクラスにパラメータリストを設定します。

@SuppressWarnings("unchecked")
public List<Item> findByColors(List<String> colors) {
    String sql = getQueryString(Item.FIND_BY_COLORS, Item.class);
    sql = setParameterList(sql, "colors", colors);

    return entityManager
            .createNativeQuery(sql, Item.class)
            .setParameter("shape", 'BOX')
            .getResultList();
}

クエリ文字列を手動で作成する必要はありません。通常どおり、他のパラメータを設定できます。

ヘルパーメソッド:

String setParameterList(String sql, String name, Collection<String> values) {
    return sql.replaceFirst(":" + name, String.join("','", values));
}

String getQueryString(String queryName, Class<?> resultClass) {
    return entityManager
            .createNamedQuery(queryName, resultClass)
            .unwrap(org.hibernate.query.Query.class) // Provider specific
            .getQueryString();
}

つまり、基本的にはからクエリ文字列を読み取り、orm.xmlパラメータリストを手動で設定してから、ネイティブJPAクエリを作成します。残念ながら、createNativeQuery().getResultList()結果クラスを渡したにもかかわらず、型なしクエリと型なしリストが返されます。したがって、@SuppressWarnings("unchecked")

欠点:クエリを実行せずにアンラップすることは、Hibernate以外のJPAプロバイダーにとってより複雑または不可能な場合があります。たとえば、EclipseLinkでは次のように機能する可能性があります(テストされていない、JPAクエリオブジェクトからSQL文字列を取得できますか?):

Session session = em.unwrap(JpaEntityManager.class).getActiveSession();
DatabaseQuery databaseQuery =     query.unwrap(EJBQueryImpl.class).getDatabaseQuery();
databaseQuery.prepareCall(session, new DatabaseRecord());
Record r = databaseQuery.getTranslationRow();
String bound = databaseQuery.getTranslatedSQLString(session, r);
String sqlString = databaseQuery.getSQLString();

別の方法として、クエリをテキストファイルに保存し、そこから読み取るコードを追加することもできます。

于 2020-02-08T21:20:24.033 に答える
0

次のように単純にすることができます。

@Query(nativeQuery =true,value = "SELECT * FROM Employee as e WHERE e.employeeName IN (:names)")  
 List<Employee> findByEmployeeName(@Param("names") List<String> names);
于 2020-07-14T15:16:08.003 に答える
0

リストをパラメーターとして渡すことはできますが、次のようになります。

  • を作成し@NamedNativeQueryて使用する.createNamedQuery()場合は、使用した名前付きパラメーターを使用しません?1(位置パラメーター)。0ではなく1から始まります。

  • を使用する場合は.createNativeQuery(String)、namedparamを使用できます。

于 2021-09-17T11:03:38.203 に答える
-5

(?userIdList)の代わりにこれを試すことができます: userIdList)

@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"
)
于 2017-07-18T09:53:24.080 に答える