将参数设置为IN表达式的列表
每当我尝试将列表设置为在IN表达式中使用的参数时,我都会得到一个Illegal参数exception。 互联网上的各种post似乎表明这是可能的,但它肯定不适合我。 我正在使用Glassfish V2.1和Toplink。
有没有其他人能够让这个工作,如果是这样的话怎么样?
这是一些示例代码:
List 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:您试图为参数accountIds设置类型类java.util.Arrays $ ArrayList的值,具有类java.lang.Long的预期类型来自查询字符串SELECT a.accountManager.loginName FROM Account a WHERE a .id IN(:accountIds)。 at oracle.toplink.essentials.internal.ejb.cmp3.base.EJBQueryImpl.setParameterInternal(EJBQueryImpl.java:663) at oracle.toplink.essentials.internal.ejb.cmp3.EJBQueryImpl.setParameter(EJBQueryImpl.java:202) 在com.corenap.newtDAO.ContactDaoBean.getNotificationAddresses(ContactDaoBean.java:437) at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39) at 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) at com.sun.ejb.containers.BaseContainer.invokeTargetBeanMethod(BaseContainer.java:2920) at com.sun.ejb.containers.BaseContainer.intercept(BaseContainer.java:4011) at com.sun.ejb.containers.EJBObjectInvocationHandler.invoke(EJBObjectInvocationHandler.java:203) ......还有67个
您的JPQL无效,请删除括号
List 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();
我找到了答案,在JPA 1.0中不支持列表作为参数; 但是,JPA 2.0支持它。
Glassfish v2.1的默认持久性提供程序是实现JPA 1.0的Toplink,要获得JPA 2.0,您需要EclipseLink,这是Glassfish v3预览的默认设置,或者可以插入到v2.1中。
– 罗兰
希望这对某人有所帮助。 我遇到了这个问题并做了以下事情来解决(使用eclipselink 2.2.0)
-
我在类路径中有JavaEE jar以及jpa 2 jar(javax.persistence * 2 *)。 从类路径中删除了JavaEE。
-
我正在使用像
" idItm IN ( :itemIds ) "
,它抛出exception:
类型类java.util.ArrayList,用于参数itemIds,具有来自查询字符串的类java.lang.String的预期类型
解决方案:我刚刚将in条件更改为" idItm IN :itemIds "
,即我删除了括号()。
简单地说,参数将是List并将其设置为
"...WHERE a.id IN (:ids)") .setParameter("ids", yourlist)
这适用于JPA 1.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 > size; i++) { queryString = queryString.concat(" "+field+" = '"+collection.get(i)+"'"); if(i > size-1) { queryString = queryString.concat(" OR"); } } queryString = queryString.concat(" )"); return queryString; }
请改用NamedQuery:
List 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")
尝试使用此代码而不是@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 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 list = new ArrayList (); list.add(122); list.add(132); list.add(112); System.out.println(in("myfield", list)); }
这给出了输出:AND(myfield =’122’或myfield =’132’或myfield =’112’)
您也可以尝试这种语法。
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);
- Java程序故意填写PermGen?
- glassfish服务器JDK / JRE问题
- 想要使用jsp显示文件列表
- 无法在Eclipse中将应用程序部署到Glassfish 4.1
- 如何使用Java EE 7和Glassfish 4在IntelliJ IDEA Community Edition中创建Java Servlet应用程序?
- 使用JPA / EclipseLink / EJB从Java Web应用程序访问多个数据库
- 我可以(以及如何)使用EJB模块中的javax.naming.Context#lookup查找CDI托管bean吗?
- 如何找到glassfish服务器的servlet API版本?
- glassfish的基本身份validation失败