Setting a parameter as a list for an IN expression

岁酱吖の 提交于 2019-11-27 08:17:18
James

Your JPQL is invalid, remove the brackets

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();

I found the answer, providing a list as a parameter is not supported in JPA 1.0; however, it is supported in JPA 2.0.

The default persistence provider for Glassfish v2.1 is Toplink which implements JPA 1.0, to get JPA 2.0 you need EclipseLink which is the default for the Glassfish v3 preview or can be plugged into v2.1.

- Loren

dillip

Hope this helps some one. I have faced the issue and did the following to resolve (using eclipselink 2.2.0)

  1. I had JavaEE jar as well as jpa 2 jar(javax.persistence*2*) in the class path. Removed the JavaEE from the class path.

  2. I was using something like " idItm IN ( :itemIds ) " which was throwing the exception :

type class java.util.ArrayList for parameter itemIds with expected type of class java.lang.String from query string

Solution: I just changed the in condition to " idItm IN :itemIds ", i.e. I removed the brackets ().

Simply, the parameter will be List and set it as

"...WHERE a.id IN (:ids)")
.setParameter("ids", yourlist)

This works for JPA 1.0

Oh, and if you can't use EclipseLink for some reason then here is a method you can use to add the needed bits to your query. Just insert the resulting string into your query where you would put "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;
    }
toquart

Use NamedQuery instead:

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

Add the named query to your entity

@NamedQuery(name = "Account.findByIdList", query = "SELECT a.accountManager.loginName FROM Account a WHERE a.id IN :ids")

IN :ids instead of IN (:ids) - will work.

Try this code instead of the one supplied by @Szymon Tarnowski to add the OR list.. warning if you have hundreds of IDs though, you might break whatever limit is in place regarding the max length of a query.

/**
 * @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;
}

To test this:

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));
}

Which gave output: AND ( myfield = '122' OR myfield = '132' OR myfield = '112')

You can also try this syntax.

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;
}

And put into query, "Select * from Class where field in " + Class.generateCollection(list);

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!