29

IN 式で使用するパラメータとしてリストを設定しようとすると、不正な引数の例外が発生します。インターネット上のさまざまな投稿は、これが可能であることを示しているようですが、私にとってはうまくいきません. ToplinkでGlassfish V2.1を使用しています。

他の誰かがこれを機能させることができましたか?

ここにいくつかのコード例があります:

List<String> logins = em.createQuery("SELECT a.accountManager.loginName " +
    "FROM Account a " +
    "WHERE a.id IN (:ids)")
    .setParameter("ids",Arrays.asList(new Long(1000100), new Long(1000110)))
    .getResultList();

およびスタック トレースの関連部分:

java.lang.IllegalArgumentException: クエリ文字列 SELECT a.accountManager.loginName FROM Account a WHERE a から予期されるクラス java.lang.Long の型で、パラメーター accountIds の型クラス java.util.Arrays$ArrayList の値を設定しようとしました.id IN (:accountIds)。
oracle.toplink.essentials.internal.ejb.cmp3.base.EJBQueryImpl.setParameterInternal(EJBQueryImpl.java:663)で
oracle.toplink.essentials.internal.ejb.cmp3.EJBQueryImpl.setParameter(EJBQueryImpl.java:202)で
com.corenap.newtDAO.ContactDaoBean.getNotificationAddresses (ContactDaoBean.java:437) で
sun.reflect.NativeMethodAccessorImpl.invoke0(ネイティブメソッド)
sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39) で
sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25) で
java.lang.reflect.Method.invoke(Method.java:597) で
com.sun.enterprise.security.application.EJBSecurityManager.runMethod(EJBSecurityManager.java:1011) で
com.sun.enterprise.security.SecurityUtil.invoke(SecurityUtil.java:175) で
com.sun.ejb.containers.BaseContainer.invokeTargetBeanMethod(BaseContainer.java:2920) で
com.sun.ejb.containers.BaseContainer.intercept(BaseContainer.java:4011) で
com.sun.ejb.containers.EJBObjectInvocationHandler.invoke(EJBObjectInvocationHandler.java:203) で
... 67 以上
4

9 に答える 9

49

JPQL が無効です。括弧を削除してください

List<String> logins = em.createQuery("SELECT a.accountManager.loginName " +
    "FROM Account a " +
    "WHERE a.id IN :ids")
    .setParameter("ids",Arrays.asList(new Long(1000100), new Long(1000110)))
    .getResultList();
于 2011-11-01T13:58:28.887 に答える
20

リストをパラメーターとして提供することは、JPA 1.0 ではサポートされていません。ただし、JPA 2.0 ではサポートされています。

Glassfish v2.1 のデフォルトの永続化プロバイダは、JPA 1.0 を実装する Toplink です。JPA 2.0 を取得するには、Glassfish v3 プレビューのデフォルトであるか、v2.1 にプラグインできる EclipseLink が必要です。

- ローレン

于 2009-10-13T16:48:40.673 に答える
13

これが誰かに役立つことを願っています。私はこの問題に直面し、解決するために次のことを行いました (eclipselink 2.2.0 を使用)

  1. クラスパスにJavaEE jarとjpa 2 jar(javax.persistence*2*)がありました。クラスパスから JavaEE を削除しました。

  2. 私は " idItm IN ( :itemIds ) "例外をスローしていたようなものを使用していました:

クエリ文字列からクラス java.lang.String の予想される型を持つパラメータ itemIds の型クラス java.util.ArrayList

解決策: in 条件を に変更しました " idItm IN :itemIds "。つまり、括弧 () を削除しました。

于 2011-07-07T10:30:06.327 に答える
0

なんらかの理由で EclipseLink を使用できない場合は、クエリに必要なビットを追加するために使用できる方法を次に示します。結果の文字列をクエリに挿入するだけで、「a.id IN (:ids)」を入力できます。

    /** 
     * @param field The jpql notation for the field you want to evaluate
     * @param collection The collection of objects you want to test against
     * @return Jpql that can be concatenated into a query to test if a feild is in a collection of objects
     */
    public String in(String field, List collection) {
        String queryString = new String();
        queryString = queryString.concat(" AND (");
        int size = collection.size();
        for(int i = 0; i &gt size; i++) {
            queryString = queryString.concat(" "+field+" = '"+collection.get(i)+"'");
            if(i &gt size-1) {
                queryString = queryString.concat(" OR");
            }
        }
        queryString = queryString.concat(" )");
        return queryString;
    }
于 2010-03-17T20:39:25.900 に答える
0

代わりに NamedQuery を使用します。

List<String> logins = em.createNamedQuery("Account.findByIdList").setParameter("ids", Arrays.asList(new Long(1000100), new Long(1000110))).getResultList();

名前付きクエリをエンティティに追加します

@NamedQuery(name = "Account.findByIdList", query = "SELECT a.accountManager.loginName FROM Account a WHERE a.id IN :ids")
于 2015-03-24T17:18:06.167 に答える
-1

@Szymon Tarnowski が提供するコードの代わりにこのコードを試して、OR リストを追加してください。ただし、数百の ID がある場合は、クエリの最大長に関して設定されている制限を破る可能性があります。

/**
 * @param field
 *           The jpql notation for the field you want to evaluate
 * @param collection
 *           The collection of objects you want to test against
 * @return Jpql that can be concatenated into a query to test if a feild is
 *         in a collection of objects
 */
public static String in(String field, List<Integer> idList) {
  StringBuilder sb = new StringBuilder();
  sb.append(" AND (");
  for(Integer id : idList) {
    sb.append(" ").append(field).append(" = '").append(id).append("'").append(" OR ");
  }
  String result = sb.toString();
  result = result.substring(0, result.length() - 4); // Remove last OR
  result += ")";
  return result;
}

これをテストするには:

public static void main(String[] args) {
  ArrayList<Integer> list = new ArrayList<Integer>();
  list.add(122);
  list.add(132);
  list.add(112);
  System.out.println(in("myfield", list));
}

どちらが出力したか: AND ( myfield = '122' OR myfield = '132' OR myfield = '112')

于 2012-07-25T01:33:51.960 に答える
-3

この構文を試すこともできます。

static public String generateCollection(List list){
    if(list == null || list.isEmpty())
        return "()";
    String result = "( ";
    for(Iterator it = list.iterator();it.hasNext();){
        Object ob = it.next();
        result += ob.toString();
        if(it.hasNext())
            result += " , ";
    }
    result += " )";
    return result;
}

そしてクエリに入れると、"Select * from Class where field in " + Class.generateCollection(list);

于 2011-11-01T13:37:22.167 に答える