문제

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: You have attempted to set a value of type class java.util.Arrays$ArrayList for parameter accountIds with expected type of class java.lang.Long from query string 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)
at 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)
at java.lang.reflect.Method.invoke(Method.java:597)
at com.sun.enterprise.security.application.EJBSecurityManager.runMethod(EJBSecurityManager.java:1011)
at 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 more
도움이 되었습니까?

해결책

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

다른 팁

JPA 1.0에서는 매개 변수로 목록을 제공하는 답변을 찾았습니다. 그러나 JPA 2.0에서 지원됩니다.

Glassfish v2.1의 기본 지속성 제공 업체는 JPA 1.0을 구현하는 Toplink이며 JPA 2.0을 얻으려면 Glassfish V3 미리보기의 기본값 인 eclipselink가 필요하거나 v2.1에 연결할 수 있습니다.

- 로렌

이것이 어떤 도움이되기를 바랍니다. 나는 문제에 직면했고 해결하기 위해 다음을 수행했습니다 (Eclipselink 2.2.0 사용).

  1. 나는 클래스 경로에 JPA 2 항아리 (javax.persistence*2*)뿐만 아니라 Javaee Jar를 가졌습니다. 수업 경로에서 Javaee를 제거했습니다.

  2. 나는 같은 것을 사용하고 있었다 " idItm IN ( :itemIds ) " 예외를 던지고 있던 것 :

query string에서 java.lang.string의 예상 유형의 매개 변수 itemids에 대한 class java.util.arraylist를 입력하십시오.

해결책 : 방금 상태를 변경했습니다 " idItm IN :itemIds ", 즉 나는 브래킷을 제거했다 ().

간단히 말하면 매개 변수가 나열되어 다음과 같이 설정됩니다.

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

대신 pamedQuery를 사용하십시오.

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

에서 : ID 대신에 in (: ids) - 작동합니다.

@szymon tarnowski가 제공 한 코드 대신 또는 목록을 추가하려면이 코드를 사용해보십시오. 경고 그러나 수백 개의 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));
}

출력을 제공했습니다.

이 구문을 시도 할 수도 있습니다.

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

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top