使用实体列表的JPA Criteria API持久字段IN表达式

时间:2013-09-04 22:30:43

标签: java hibernate jpa eclipselink jpql

我正在尝试类似之前发布的这个问题:

JPA Criteria API IN expression Parameter list

但是,我正在尝试使用实体列表而不是Longs(PKs)列表,例如:

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

请假设this.em属于EntityManager类型。 Task实体具有关联的所有者,映射如下:

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

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

        ...
}

我知道我以前使用过与JPQL类似的东西,但我不知道如何使用Criteria API完成它。

使用上面的代码导致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

这个问题基本上是部分... AND (t1.OWNER_USER_ID IN (?))) ...,因为它假定使用某种List。这是不可取的。

我记得曾经用JPQL和Hibernate作为JPA提供者做过类似的事情,现在问题就在这里。

JPQL ... WHERE task.owner IN :filterUsers是否存在等效标准,其中:filterUsers是使用query.setParameter( "filterUsers", filterUsers )的标准命名参数,后者被声明为List<User> filterUsers = ...?如果是这样,它是如何完成的?

PS:很抱歉德国的错误消息,我真的没有本地化的错误消息(我不能重复太多次了!)。

1 个答案:

答案 0 :(得分:1)

你可以试试这个,

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