| Summary: | In-Clause fails for elementCollection-mapping and a collection as parameter | ||
|---|---|---|---|
| Product: | z_Archived | Reporter: | Igor Mukhin <iimuhin> |
| Component: | Eclipselink | Assignee: | Nobody - feel free to take it <nobody> |
| Status: | RESOLVED FIXED | QA Contact: | |
| Severity: | normal | ||
| Priority: | P2 | CC: | iimuhin, jamesssss, rmacdonald, tom.ware |
| Version: | unspecified | ||
| Target Milestone: | --- | ||
| Hardware: | PC | ||
| OS: | Windows 7 | ||
| Whiteboard: | |||
Setting target and priority. See the following page for details about these fields: http://wiki.eclipse.org/EclipseLink/Development/Bugs/Guidelines The problem is the extra list parentheses around the in clause. This is disallowed in JPA 2.0, rejected by eclipselink, and supported by hibernate. http://opensource.atlassian.com/projects/hibernate/browse/HHH-5126 The generated sql is something like: SELECT data FROM table WHERE (col IN ((?,?))) which fails, as the IN argument is actually a list of list. We need it to be: SELECT data FROM table WHERE (col IN (?,?)) As a quick fix (code refactoring could be improved), replace the existing code with the following code: Class: org.eclipse.persistence.internal.jpa.querydef.ExpressionImpl Method: public Predicate in(Expression<?>... values) public Predicate in(Expression<?>... values) { if (values != null) { List list = new ArrayList(); list.add(this); if (values.length == 1 && ((InternalExpression) values[0]).isSubquery()) { list.add(values[0]); return new CompoundExpressionImpl(this.metamodel, this.currentNode.in(((SubQueryImpl) values[0]).subQuery), list, "in"); } else if (values.length == 1){// ADD THIS ADDITIONAL ELSE STATEMENT Expression exp = values[0]; if (!((InternalExpression) exp).isLiteral() && !((InternalExpression) exp).isParameter()) { Object[] params = new Object[]{exp}; throw new IllegalArgumentException(ExceptionLocalization.buildMessage("CRITERIA_NON_LITERAL_PASSED_TO_IN",params)); } else { list.add(exp); } return new CompoundExpressionImpl(this.metamodel, this.currentNode.in(((InternalSelection)exp).getCurrentNode()), list, "in"); } else { List<Object> inValues = new ArrayList<Object>(); for (Expression exp : values) { if (!((InternalExpression) exp).isLiteral() && !((InternalExpression) exp).isParameter()) { Object[] params = new Object[]{exp}; throw new IllegalArgumentException(ExceptionLocalization.buildMessage("CRITERIA_NON_LITERAL_PASSED_TO_IN",params)); } else { list.add(exp); inValues.add(((InternalSelection)exp).getCurrentNode()); } } return new CompoundExpressionImpl(this.metamodel, this.currentNode.in(inValues), list, "in"); } } throw new IllegalArgumentException(ExceptionLocalization.buildMessage("NULL_PASSED_TO_EXPRESSION_IN")); } Issue was special validation for direct collection, was not checking for a collection, but validation of type is not correct anyway as types may not be equal but may be convertable (long, int). See, Bug#314025 The Eclipselink project has moved to Github: https://github.com/eclipse-ee4j/eclipselink The Eclipselink project has moved to Github: https://github.com/eclipse-ee4j/eclipselink |
Build Identifier: 2.1.1 @Entity public class Person { @Id private int id; @ElementCollection private List<String> strings = new Vector<String>(); } The next query is ok: select p from Person p where p.strings in (?1, ?2) This query will fail: TypedQuery<Person> q = em.createQuery("select p from Person p where p.strings in ?1", Person.class); List<String> names = Arrays.asList(new String[] { "str1", "str2" }); q.setParameter(1, names); List<Person> persons = q.getResultList(); Exception: Exception Description: The class of the argument for the object comparison is incorrect. Expression: [null] Mapping: [org.eclipse.persistence.mappings.DirectCollectionMapping[strings]] Argument: [[str1, str2]] Query: ReadAllQuery(referenceClass=Person sql="SELECT t0.ID FROM PERSON t0, Person_STRINGS t1 WHERE ((t1.STRINGS IN ?) AND (t1.Person_ID = t0.ID))") Reproducible: Always Steps to Reproduce: see description