我正在尝试类似之前发布的这个问题:
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:很抱歉德国的错误消息,我真的没有本地化的错误消息(我不能重复太多次了!)。
答案 0 :(得分:1)
你可以试试这个,
Criteria criteria = getSession().createCriteria(Task .class);
criteria.createAlias("owner.id", "filterUsers");
criteria.add(Restrictions.in("filterUsers", <List that contains user ids>));