简体   繁体   中英

JPA Criteria API persistent field IN expression using list of entities

I'm trying something similar to this question posted before:

JPA Criteria API IN expression Parameter list

However, I'm trying to use a list of entities instead of a list of Longs (PKs), like:

public List<Task> generateFilteredQuery( List<User> filterUsers )
{
    CriteriaBuilder cb = this.em.getCriteriaBuilder();
    CriteriaQuery<Task> criteriaQuery = cb.createQuery( Task.class );
    Root<Task> root = criteriaQuery.from( Task.class );

    criteriaQuery.select( root ).where( root.get( "owner" ).in( filterUsers ) );

    return this.em.createQuery( criteriaQuery ).getResultList();
}

Please assume this.em to be of type EntityManager . The Task entity has an associated owner, mapped like this:

@Entity
@Table( name = "TASKS" )
public class Task implements Serializable
{
        ...

        @ManyToOne( fetch = FetchType.EAGER )
        @JoinColumn( name = "OWNER_USER_ID", referencedColumnName = "USER_ID" )
        private User owner;

        ...
}

I know I have used something similar from JPQL before, but I don't see how it is done using the Criteria API.

Using the above code causes a DB exception to ocurr:

Caused by: Exception [EclipseLink-4002] (Eclipse Persistence Services - 2.4.1.v20121003-ad44345): org.eclipse.persistence.exceptions.DatabaseException
Internal Exception: com.microsoft.sqlserver.jdbc.SQLServerException: Fehler beim Konvertieren des nvarchar-Datentyps in bigint.
Error Code: 8114
Call: SELECT DISTINCT t1.TASK_ID, t1.CLIENT_ID, t1.CLOSE_TIME, t1.CLOSE_USER_ID, t1.TASK_DATE, t1.TASK_DATE_ID, t1.LASTACTION, t1.LASTHOST_ID, t1.LASTTIME, t1.LASTUSER_ID, t1.OBJECT_ID, t1.OWNER_USER_ID, t1.STATUS_TEXT, t1.STATUS, t1.TABLE_ID, t1.TASK_TRIGGER_ID, t1.TASK_TYPE FROM TASKS t1 LEFT OUTER JOIN TASK_TYPES t2 ON (t2.TASK_TYPE_ID = t1.TASK_TYPE) LEFT OUTER JOIN TASK_TRIGGERS t3 ON (t3.TASK_TRIGGER_ID = t1.TASK_TRIGGER_ID) LEFT OUTER JOIN USERS t4 ON (t4.USER_ID = t1.LASTUSER_ID) LEFT OUTER JOIN USERS t5 ON (t5.USER_ID = t1.CLOSE_USER_ID), USERS t0 WHERE ((((t1.CLIENT_ID = ?) AND ((((((LOWER(t2.NAME) LIKE ? OR LOWER(t1.STATUS) LIKE ?) OR LOWER(t1.STATUS_TEXT) LIKE ?) OR LOWER(t0.USER_NAME) LIKE ?) OR LOWER(t3.DESCRIPTION) LIKE ?) OR LOWER(t4.USER_NAME) LIKE ?) OR LOWER(t5.USER_NAME) LIKE ?)) AND (t1.OWNER_USER_ID IN (?))) AND (t0.USER_ID = t1.OWNER_USER_ID)) ORDER BY t1.LASTTIME DESC
    bind => [1, %%, %%, %%, %%, %%, %%, %%, User [id=437, getUserName()=bla, clients=[], .................]]
Query: ReadAllQuery(referenceClass=Task sql="SELECT DISTINCT t1.TASK_ID, t1.CLIENT_ID, t1.CLOSE_TIME, t1.CLOSE_USER_ID, t1.TASK_DATE, t1.TASK_DATE_ID, t1.LASTACTION, t1.LASTHOST_ID, t1.LASTTIME, t1.LASTUSER_ID, t1.OBJECT_ID, t1.OWNER_USER_ID, t1.STATUS_TEXT, t1.STATUS, t1.TABLE_ID, t1.TASK_TRIGGER_ID, t1.TASK_TYPE FROM TASKS t1 LEFT OUTER JOIN TASK_TYPES t2 ON (t2.TASK_TYPE_ID = t1.TASK_TYPE) LEFT OUTER JOIN TASK_TRIGGERS t3 ON (t3.TASK_TRIGGER_ID = t1.TASK_TRIGGER_ID) LEFT OUTER JOIN USERS t4 ON (t4.USER_ID = t1.LASTUSER_ID) LEFT OUTER JOIN USERS t5 ON (t5.USER_ID = t1.CLOSE_USER_ID), USERS t0 WHERE ((((t1.CLIENT_ID = ?) AND ((((((LOWER(t2.NAME) LIKE ? OR LOWER(t1.STATUS) LIKE ?) OR LOWER(t1.STATUS_TEXT) LIKE ?) OR LOWER(t0.USER_NAME) LIKE ?) OR LOWER(t3.DESCRIPTION) LIKE ?) OR LOWER(t4.USER_NAME) LIKE ?) OR LOWER(t5.USER_NAME) LIKE ?)) AND (t1.OWNER_USER_ID IN (?))) AND (t0.USER_ID = t1.OWNER_USER_ID)) ORDER BY t1.LASTTIME DESC")
    at org.eclipse.persistence.exceptions.DatabaseException.sqlException(DatabaseException.java:333)
    at org.eclipse.persistence.internal.databaseaccess.DatabaseAccessor.basicExecuteCall(DatabaseAccessor.java:646)
    at org.eclipse.persistence.internal.databaseaccess.DatabaseAccessor.executeCall(DatabaseAccessor.java:537)
    at org.eclipse.persistence.internal.sessions.AbstractSession.basicExecuteCall(AbstractSession.java:1800)
    at org.eclipse.persistence.sessions.server.ServerSession.executeCall(ServerSession.java:566)
    at org.eclipse.persistence.sessions.server.ClientSession.executeCall(ClientSession.java:240)
    at org.eclipse.persistence.internal.queries.DatasourceCallQueryMechanism.executeCall(DatasourceCallQueryMechanism.java:207)
    at org.eclipse.persistence.internal.queries.DatasourceCallQueryMechanism.executeCall(DatasourceCallQueryMechanism.java:193)
    at org.eclipse.persistence.internal.
INFO: queries.DatasourceCallQueryMechanism.executeSelectCall(DatasourceCallQueryMechanism.java:264)
    at org.eclipse.persistence.internal.queries.DatasourceCallQueryMechanism.selectAllRows(DatasourceCallQueryMechanism.java:648)
    at org.eclipse.persistence.internal.queries.ExpressionQueryMechanism.selectAllRowsFromTable(ExpressionQueryMechanism.java:2706)
    at org.eclipse.persistence.internal.queries.ExpressionQueryMechanism.selectAllRows(ExpressionQueryMechanism.java:2659)
    at org.eclipse.persistence.queries.ReadAllQuery.executeObjectLevelReadQuery(ReadAllQuery.java:421)
    at org.eclipse.persistence.queries.ObjectLevelReadQuery.executeDatabaseQuery(ObjectLevelReadQuery.java:1150)
    at org.eclipse.persistence.queries.DatabaseQuery.execute(DatabaseQuery.java:852)
    at org.eclipse.persistence.queries.ObjectLevelReadQuery.execute(ObjectLevelReadQuery.java:1109)
    at org.eclipse.persistence.queries.ReadAllQuery.execute(ReadAllQuery.java:393)
    at org.eclipse.persistence.queries.ObjectLevelReadQuery.executeInUnitOfWork(ObjectLevelReadQuery.java:1197)
    at org.eclipse.persistence.internal.sessions.UnitOfWorkImpl.internalExecuteQuery(UnitOfWorkImpl.java:2875)
    at org.eclipse.persistence.internal.sessions.AbstractSession.executeQuery(AbstractSession.java:1602)
    at org.eclipse.persistence.internal.sessions.AbstractSession.executeQuery(AbstractSession.java:1584)
    at org.eclipse.persistence.internal.sessions.AbstractSession.executeQuery(AbstractSession.java:1549)
    at org.eclipse.persistence.internal.jpa.QueryImpl.executeReadQuery(QueryImpl.java:231)
    at org.eclipse.persistence.internal.jpa.QueryImpl.getResultList(QueryImpl.java:411)
    at com.sun.enterprise.container.common.impl.QueryWrapper.getResultList(QueryWrapper.java:195)
    at com.sun.enterprise.container.common.impl.TypedQueryWrapper.getResultList(TypedQueryWrapper.java:129)
    at de.bnext.core.base.repository.BaseEntityRepositoryBean.findBy(BaseEntityRepositoryBean.java:448)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:601)
    at org.glassfish.ejb.security.application.EJBSecurityManager.runMethod(EJBSecurityManager.java:1052)
    at org.glassfish.ejb.security.application.EJBSecurityManager.invoke(EJBSecurityManager.java:1124)
    at com.sun.ejb.containers.BaseContainer.invokeBeanMethod(BaseContainer.java:5388)
    at com.sun.ejb.EjbInvocation.invokeBeanMethod(EjbInvocation.java:619)
    at com.sun.ejb.containers.interceptors.AroundInvokeChainImpl.invokeNext(InterceptorManager.java:800)
    at com.sun.ejb.EjbInvocation.proceed(EjbInvocation.java:571)
    at de.bnext.core.interceptor.persistence.PersistencePropertiesInterceptor.injectPersistenceProperties(PersistencePropertiesInterceptor.java:81)
    at sun.reflect.GeneratedMethodAccessor1084.invoke(Unknown Source)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:601)
    at com.sun.ejb.containers.interceptors.AroundInvokeInterceptor.intercept(InterceptorManager.java:861)
    at com.sun.ejb.containers.interceptors.AroundInvokeChainImpl.invokeNext(InterceptorManager.java:800)
    at com.sun.ejb.EjbInvocation.proceed(EjbInvocation.java:571)
    at de.bnext.core.interceptor.common.NullCheckInterceptor.checkNull(NullCheckInterceptor.java:85)
    at sun.reflect.GeneratedMethodAccessor1083.invoke(Unknown Source)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:601)
    at com.sun.ejb.containers.interceptors.AroundInvokeInterceptor.intercept(InterceptorManager.java:861)
    at com.sun.ejb.containers.interceptors.AroundInvokeChainImpl.invokeNext(InterceptorManager.java:800)
    at com.sun.ejb.EjbInvocation.proceed(EjbInvocation.java:571)
    at de.bnext.core.interceptor.logging.LoggingInterceptor.logMethod(LoggingInterceptor.java:90)
    at sun.reflect.GeneratedMethodAccessor1078.invoke(Unknown Source)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:601)
    at com.sun.ejb.containers.interceptors.AroundInvokeInterceptor.intercept(InterceptorManager.java:861)
    at com.sun.ejb.containers.interceptors.AroundInvokeChainImpl.invokeNext(InterceptorManager.java:800)
    at com.sun.ejb.EjbInvocation.proceed(EjbInvocation.java:571)
    at org.jboss.weld.ejb.SessionBeanInterceptor.aroundInvoke(SessionBeanInterceptor.java:42)
    at sun.reflect.GeneratedMethodAccessor1077.invoke(Unknown Source)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:601)
    at com.sun.ejb.containers.interceptors.AroundInvokeInterceptor.intercept(InterceptorManager.java:861)
    at com.sun.ejb.containers.interceptors.AroundInvokeChainImpl.invokeNext(InterceptorManager.java:800)
    at com.sun.ejb.EjbInvocation.proceed(EjbInvocation.java:571)
    at com.sun.ejb.containers.interceptors.SystemInterceptorProxy.doAround(SystemInterceptorProxy.java:162)
    at com.sun.ejb.containers.interceptors.SystemInterceptorProxy.aroundInvoke(SystemInterceptorProxy.java:144)
    at sun.reflect.GeneratedMethodAccessor1076.invoke(Unknown Source)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:601)
    at com.sun.ejb.containers.interceptors.AroundInvokeInterceptor.intercept(InterceptorManager.java:861)
    at com.sun.ejb.containers.interceptors.AroundInvokeChainImpl.invokeNext(InterceptorManager.java:800)
    at com.sun.ejb.containers.interceptors.InterceptorManager.intercept(InterceptorManager.java:370)
    at com.sun.ejb.containers.BaseContainer.__intercept(BaseContainer.java:5360)
    at com.sun.ejb.containers.BaseContainer.intercept(BaseContainer.java:5348)
    at com.sun.ejb.containers.EJBLocalObjectInvocationHandler.invoke(EJBLocalObjectInvocationHandler.java:214)
    ... 120 more
Caused by: com.microsoft.sqlserver.jdbc.SQLServerException: Fehler beim Konvertieren des nvarchar-Datentyps in bigint.
    at com.microsoft.sqlserver.jdbc.SQLServerException.makeFromDatabaseError(SQLServerException.java:216)
    at com.microsoft.sqlserver.jdbc.SQLServerResultSet$FetchBuffer.nextRow(SQLServerResultSet.java:4853)
    at com.microsoft.sqlserver.jdbc.SQLServerResultSet.fetchBufferNext(SQLServerResultSet.java:1781)
    at com.microsoft.sqlserver.jdbc.SQLServerResultSet.next(SQLServerResultSet.java:1034)
    at com.sun.gjc.spi.base.ResultSetWrapper.next(ResultSetWrapper.java:103)
    at org.eclipse.persistence.internal.databaseaccess.DatabaseAccessor.processResultSet(DatabaseAccessor.java:715)
    at org.eclipse.persistence.internal.databaseaccess.DatabaseAccessor.basicExecuteCall(DatabaseAccessor.java:623)
    ... 194 more

The problem with this basically is the part ... AND (t1.OWNER_USER_ID IN (?))) ... as this assumes some kind of List to be used. This is not desired.

I remember having done something like that with JPQL and Hibernate as a JPA provider before, now here's the question.

Q :

Is there a Criteria equivalent for JPQL ... WHERE task.owner IN :filterUsers , where :filterUsers is a standard named paramater using query.setParameter( "filterUsers", filterUsers ) and the latter being declared as List<User> filterUsers = ... ? If so, how's it done?

PS: Sorry for the German error messages, I really h*te localized error messages (and I can't repeat that too many times!).

You can try this,

Criteria criteria = getSession().createCriteria(Task .class);                                 
criteria.createAlias("owner.id", "filterUsers");                                              
criteria.add(Restrictions.in("filterUsers", <List that contains user ids>));

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM