تعيين معلمة كقائمة للتعبير في التعبير
-
21-09-2019 - |
سؤال
كلما حاولت تعيين قائمة كمعلمة لاستخدامها في التعبير ، أحصل على استثناء وسيطة غير قانوني. يبدو أن المشاركات المختلفة على الإنترنت تشير إلى أن هذا ممكن ، لكنه بالتأكيد لا يعمل بالنسبة لي. أنا أستخدم Glassfish v2.1 مع Toplink.
هل تمكن أي شخص آخر من جعل هذا العمل ، إذا كان الأمر كذلك ، كيف؟
إليك بعض رمز المثال:
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 هو Toplink الذي ينفذ JPA 1.0 ، للحصول على JPA 2.0 ، تحتاج إلى Eclipselink وهو الافتراضي لمعاينة Glassfish V3 أو يمكن توصيله بـ V2.1.
- لورين
أمل أن هذا يساعد شخصاما. لقد واجهت المشكلة وفعلت ما يلي للحل (باستخدام Eclipselink 2.2.0)
كان لدي Javaee Jar وكذلك JPA 2 Jar (Javax.persistence*2*) في مسار الفصل. أزال جافاي من مسار الفصل.
كنت أستخدم شيئًا مثل
" idItm IN ( :itemIds ) "
الذي كان يرمي الاستثناء:
اكتب class java.util.arraylist for parameter itemids مع نوع متوقع من الفئة java.lang.string من سلسلة الاستعلام
الحل: لقد غيرت للتو الشرط إلى " idItm IN :itemIds "
, ، أي أزال الأقواس ().
ببساطة ، ستكون المعلمة قائمة وتعيينها على أنها
"...WHERE a.id IN (:ids)")
.setParameter("ids", yourlist)
هذا يعمل لصالح JPA 1.0
أوه ، وإذا لم تتمكن من استخدام Eclipselink لسبب ما ، فإليك طريقة يمكنك استخدامها لإضافة البتات المطلوبة إلى استعلامك. ما عليك سوى إدراج السلسلة الناتجة في استعلامك حيث يمكنك وضع "A.ID في (: 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;
}
استخدم اسمه بدلاً من ذلك:
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")
في: IDS بدلاً من في (: IDS) - سيعمل.
جرب هذا الرمز بدلاً من الرمز المقدم من Szymon Tarnowski لإضافة أو قائمة .. تحذير إذا كان لديك مئات من الهوية ، فقد تكسر أي حد موجود فيما يتعلق بطول الاستعلام الأقصى.
/**
* @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));
}
الذي أعطى الإخراج: و (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);