distinct(true) - 无法准备声明

时间:2014-08-20 11:24:57

标签: java hibernate entitymanager

我正在使用带有spring的hibernate。但是,在添加.distinct(true)之类的criteria.select(cb.construct(Customer.class, root.get("Name"))).distinct(true);时。然后我收到以下异常:

Exception in thread "AWT-EventQueue-0" javax.persistence.PersistenceException: org.hibernate.exception.SQLGrammarException: could not prepare statement
    at org.hibernate.ejb.AbstractEntityManagerImpl.convert(AbstractEntityManagerImpl.java:1387)
    at org.hibernate.ejb.AbstractEntityManagerImpl.convert(AbstractEntityManagerImpl.java:1310)
    at org.hibernate.ejb.QueryImpl.getResultList(QueryImpl.java:273)
    at org.hibernate.ejb.criteria.CriteriaQueryCompiler$3.getResultList(CriteriaQueryCompiler.java:254)
    at com.limitCalculator.dao.FilterDaoImpl.getFilter(FilterDaoImpl.java:83)
    at com.limitCalculator.dao.FilterDaoImpl$$FastClassByCGLIB$$a62bf500.invoke(<generated>)
    at org.springframework.cglib.proxy.MethodProxy.invoke(MethodProxy.java:204)
    at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.invokeJoinpoint(CglibAopProxy.java:698)
    at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:150)
    at org.springframework.transaction.interceptor.TransactionInterceptor$1.proceedWithInvocation(TransactionInterceptor.java:96)
    at org.springframework.transaction.interceptor.TransactionAspectSupport.invokeWithinTransaction(TransactionAspectSupport.java:260)
    at org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:94)
    at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:172)
    at org.springframework.aop.framework.CglibAopProxy$DynamicAdvisedInterceptor.intercept(CglibAopProxy.java:631)
    at com.limitCalculator.dao.FilterDaoImpl$$EnhancerByCGLIB$$6ca0bd06.getFilter(<generated>)
    at com.limitCalculator.service.FilterServiceImpl.getFilter(FilterServiceImpl.java:37)
    at com.limitCalculator.gui.timerSelection.MainTabPanel.placeSelectionWithButtons(MainTabPanel.java:137)
    at com.limitCalculator.gui.timerSelection.MainTabPanel.createLayout(MainTabPanel.java:111)
    at com.limitCalculator.gui.timerSelection.MainWindow.createTabBar(MainWindow.java:132)
    at com.limitCalculator.gui.timerSelection.MainWindow.makeLayout(MainWindow.java:182)
    at com.limitCalculator.gui.timerSelection.MainWindow.access$1(MainWindow.java:172)
    at com.limitCalculator.gui.timerSelection.MainWindow$4.run(MainWindow.java:197)
    at java.awt.event.InvocationEvent.dispatch(Unknown Source)
    at java.awt.EventQueue.dispatchEventImpl(Unknown Source)
    at java.awt.EventQueue.access$400(Unknown Source)
    at java.awt.EventQueue$2.run(Unknown Source)
    at java.awt.EventQueue$2.run(Unknown Source)
    at java.security.AccessController.doPrivileged(Native Method)
    at java.security.AccessControlContext$1.doIntersectionPrivilege(Unknown Source)
    at java.awt.EventQueue.dispatchEvent(Unknown Source)
    at java.awt.EventDispatchThread.pumpOneEventForFilters(Unknown Source)
    at java.awt.EventDispatchThread.pumpEventsForFilter(Unknown Source)
    at java.awt.EventDispatchThread.pumpEventsForHierarchy(Unknown Source)
    at java.awt.EventDispatchThread.pumpEvents(Unknown Source)
    at java.awt.EventDispatchThread.pumpEvents(Unknown Source)
    at java.awt.EventDispatchThread.run(Unknown Source)
Caused by: org.hibernate.exception.SQLGrammarException: could not prepare statement
    at org.hibernate.exception.internal.SQLExceptionTypeDelegate.convert(SQLExceptionTypeDelegate.java:82)
    at org.hibernate.exception.internal.StandardSQLExceptionConverter.convert(StandardSQLExceptionConverter.java:49)
    at org.hibernate.engine.jdbc.spi.SqlExceptionHelper.convert(SqlExceptionHelper.java:125)
    at org.hibernate.engine.jdbc.internal.StatementPreparerImpl$StatementPreparationTemplate.prepareStatement(StatementPreparerImpl.java:188)
    at org.hibernate.engine.jdbc.internal.StatementPreparerImpl.prepareQueryStatement(StatementPreparerImpl.java:159)
    at org.hibernate.loader.Loader.prepareQueryStatement(Loader.java:1854)
    at org.hibernate.loader.Loader.executeQueryStatement(Loader.java:1831)
    at org.hibernate.loader.Loader.executeQueryStatement(Loader.java:1811)
    at org.hibernate.loader.Loader.doQuery(Loader.java:899)
    at org.hibernate.loader.Loader.doQueryAndInitializeNonLazyCollections(Loader.java:341)
    at org.hibernate.loader.Loader.doList(Loader.java:2516)
    at org.hibernate.loader.Loader.doList(Loader.java:2502)
    at org.hibernate.loader.Loader.listIgnoreQueryCache(Loader.java:2332)
    at org.hibernate.loader.Loader.list(Loader.java:2327)
    at org.hibernate.loader.hql.QueryLoader.list(QueryLoader.java:490)
    at org.hibernate.hql.internal.ast.QueryTranslatorImpl.list(QueryTranslatorImpl.java:355)
    at org.hibernate.engine.query.spi.HQLQueryPlan.performList(HQLQueryPlan.java:195)
    at org.hibernate.internal.SessionImpl.list(SessionImpl.java:1268)
    at org.hibernate.internal.QueryImpl.list(QueryImpl.java:101)
    at org.hibernate.ejb.QueryImpl.getResultList(QueryImpl.java:264)
    ... 33 more
Caused by: java.sql.SQLSyntaxErrorException: invalid ORDER BY expression
    at org.hsqldb.jdbc.JDBCUtil.sqlException(Unknown Source)
    at org.hsqldb.jdbc.JDBCUtil.sqlException(Unknown Source)
    at org.hsqldb.jdbc.JDBCPreparedStatement.<init>(Unknown Source)
    at org.hsqldb.jdbc.JDBCConnection.prepareStatement(Unknown Source)
    at org.apache.commons.dbcp.DelegatingConnection.prepareStatement(DelegatingConnection.java:281)
    at org.apache.commons.dbcp.PoolingDataSource$PoolGuardConnectionWrapper.prepareStatement(PoolingDataSource.java:313)
    at org.hibernate.engine.jdbc.internal.StatementPreparerImpl$5.doPrepare(StatementPreparerImpl.java:161)
    at org.hibernate.engine.jdbc.internal.StatementPreparerImpl$StatementPreparationTemplate.prepareStatement(StatementPreparerImpl.java:182)
    ... 49 more

我的hibernate查询看起来像这样:

Hibernate:

select distinct customer0_.Name as col_0_0_ 
from Customer customer0_ 
where (upper(customer0_.Name) like ?) and (upper(customer0_.City) like ?) and
    (upper(customer0_.Country) like ?) 
order by customer0_.customerNr asc

这就是我正在使用的代码:

@Transactional
@SuppressWarnings("all")
public List<Customer> getFilter(String city, String country) {
    CriteriaBuilder cb = em.getCriteriaBuilder();
    CriteriaQuery<Customer> criteria = cb.createQuery(Customer.class);
    //which table we want to fetch
    final Root root = criteria.from(Customer.class);
    List criteriaList = createWhereCritera(city, country, cb, root);

    //create statement
    criteria.select(cb.construct(Customer.class, root.get("Name"))).distinct(true);
    // Pass the criteria list to the where method of criteria query
    criteria.where(cb.and((Predicate[]) criteriaList.toArray(new Predicate[0])));
    // Order by clause
    criteria.orderBy(cb.asc(root.get("customerNr")));
    return em.createQuery(criteria).getResultList();
}

public List createWhereCritera(String city, String country, CriteriaBuilder cb,
        final Root root) {
    // This list will contain all Predicates (where clauses)
    List criteriaList = new ArrayList();
    // City: 
    Predicate predicateCity = cb.like(cb.upper(root.get("City")),city);
    criteriaList.add(predicateCity); 
    // Country: 
    Predicate predicateCountry = cb.like(cb.upper(root.get("Country")),country);
    criteriaList.add(predicateCountry);
    return criteriaList;
}   

任何建议,为什么会出现此问题以及如何获取所有不同的值?

感谢您的回答!

2 个答案:

答案 0 :(得分:1)

您的查询错误。 无论Order By has to be a part of Select clause中有什么。

当存在ORDER BY子句时,它是最后执行的子句。首先,FROM子句生成要检查的对象,WHERE子句选择要收集哪些对象作为结果。然后SELECT子句通过计算结果表达式来构建结果。最后,通过评估ORDER BY表达式来排序结果。

在ORDER BY子句中只允许直接从SELECT子句中的表达式派生的表达式。以下查询无效,因为ORDER BY表达式不是结果的一部分:

SELECT c.name
FROM Country c
WHERE c.population > 1000000
ORDER BY c.population

另一方面,以下查询有效,因为在给定国家c的情况下,可以从c评估c.population表达式:

SELECT c
FROM Country c
WHERE c.population > 1000000
ORDER BY c.population

所以请将您的查询更改为以下内容。

select distinct (customer0_.Name as col_0_0_), customer0_.customerNr from Customer customer0_ where (upper(customer0_.Name) like ?) and (upper(customer0_.City) like ?) and (upper(customer0_.Country) like ?) order by customer0_.customerNr asc

答案 1 :(得分:0)

对于条件查询,您可以根据根表的主键列通过group by进行重复数据删除:

criteria.groupBy(root.get("id")); // Assuming that Customer.id is primary key column