Some Eclipse Foundation services are deprecated, or will be soon. Please ensure you've read this important communication.

Bug 328378

Summary: In-Clause fails for elementCollection-mapping and a collection as parameter
Product: z_Archived Reporter: Igor Mukhin <iimuhin>
Component: EclipselinkAssignee: 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:

Description Igor Mukhin CLA 2010-10-21 11:43:40 EDT
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
Comment 1 Tom Ware CLA 2010-11-01 11:35:12 EDT
Setting target and priority.  See the following page for details about these
fields:

http://wiki.eclipse.org/EclipseLink/Development/Bugs/Guidelines
Comment 2 Rich MacDonald CLA 2010-12-14 11:50:53 EST
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"));
    }
Comment 3 James Sutherland CLA 2011-11-09 14:49:43 EST
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).
Comment 4 James Sutherland CLA 2011-11-16 11:23:38 EST
See, Bug#314025
Comment 5 Eclipse Webmaster CLA 2022-06-09 10:15:05 EDT
The Eclipselink project has moved to Github: https://github.com/eclipse-ee4j/eclipselink
Comment 6 Eclipse Webmaster CLA 2022-06-09 10:19:06 EDT
The Eclipselink project has moved to Github: https://github.com/eclipse-ee4j/eclipselink