使用HQL和可分页的JPA查询使用* return创建子选择并生成别名错误

时间:2017-04-21 14:15:08

标签: java mysql spring hibernate jpa

所以我想从JPA查询中做一个多对象返回,该查询也允许可分页,这样我只能返回它返回的前10个。

JPA: Query that returns multiple entities

问题在于,如果我将pageable添加到方法定义中,那么它将整个select语句捆绑在select * from(original_query)中,其中rownum< = size;。如果我删除pageable它会在没有subselect的情况下执行original_query并且工作正常。但每次我添加pageable并执行select *它会抛出以下错误,因为我没有别名的return语句。

  

线程中的异常" main" org.springframework.dao.InvalidDataAccessResourceUsageException:无法提取ResultSet; SQL [不适用];嵌套异常是org.hibernate.exception.SQLGrammarException:无法提取ResultSet       在org.springframework.orm.jpa.vendor.HibernateJpaDialect.convertHibernateAccessException(HibernateJpaDialect.java:236)       在org.springframework.orm.jpa.vendor.HibernateJpaDialect.translateExceptionIfPossible(HibernateJpaDialect.java:219)       at org.springframework.orm.jpa.AbstractEntityManagerFactoryBean.translateExceptionIfPossible(AbstractEntityManagerFactoryBean.java:491)       at org.springframework.dao.support.ChainedPersistenceExceptionTranslator.translateExceptionIfPossible(ChainedPersistenceExceptionTranslator.java:59)       在org.springframework.dao.support.DataAccessUtils.translateIfNecessary(DataAccessUtils.java:213)       at org.springframework.dao.support.PersistenceExceptionTranslationInterceptor.invoke(PersistenceExceptionTranslationInterceptor.java:147)       在org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179)       at org.springframework.data.jpa.repository.support.CrudMethodMetadataPostProcessor $ CrudMethodMetadataPopulatingMethodInterceptor.invoke(CrudMethodMetadataPostProcessor.java:133)       在org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179)       在org.springframework.aop.interceptor.ExposeInvocationInterceptor.invoke(ExposeInvocationInterceptor.java:92)       在org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179)       在org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:213)       at com.sun.proxy。$ Proxy82.retrieveQualifyingOffers(Unknown Source)       在com.comcast.qe.dataload.RunApp.main(RunApp.java:35)   引起:org.hibernate.exception.SQLGrammarException:无法提取ResultSet       在org.hibernate.exception.internal.SQLExceptionTypeDelegate.convert(SQLExceptionTypeDelegate.java:63)       在org.hibernate.exception.internal.StandardSQLExceptionConverter.convert(StandardSQLExceptionConverter.java:42)       在org.hibernate.engine.jdbc.spi.SqlExceptionHelper.convert(SqlExceptionHelper.java:111)       at org.hibernate.engine.jdbc.spi.SqlExceptionHelper.convert(SqlExceptionHelper.java:97)       at org.hibernate.engine.jdbc.internal.ResultSetReturnImpl.extract(ResultSetReturnImpl.java:79)       在org.hibernate.loader.Loader.getResultSet(Loader.java:2123)       在org.hibernate.loader.Loader.executeQueryStatement(Loader.java:1911)       在org.hibernate.loader.Loader.executeQueryStatement(Loader.java:1887)       在org.hibernate.loader.Loader.doQuery(Loader.java:932)       在org.hibernate.loader.Loader.doQueryAndInitializeNonLazyCollections(Loader.java:349)       在org.hibernate.loader.Loader.doList(Loader.java:2615)       在org.hibernate.loader.Loader.doList(Loader.java:2598)       在org.hibernate.loader.Loader.listIgnoreQueryCache(Loader.java:2430)       在org.hibernate.loader.Loader.list(Loader.java:2425)       在org.hibernate.loader.hql.QueryLoader.list(QueryLoader.java:502)       在org.hibernate.hql.internal.ast.QueryTranslatorImpl.list(QueryTranslatorImpl.java:371)       在org.hibernate.engine.query.spi.HQLQueryPlan.performList(HQLQueryPlan.java:216)       在org.hibernate.internal.SessionImpl.list(SessionImpl.java:1473)       在org.hibernate.query.internal.AbstractProducedQuery.doList(AbstractProducedQuery.java:1426)       在org.hibernate.query.internal.AbstractProducedQuery.list(AbstractProducedQuery.java:1398)       在org.hibernate.Query.getResultList(Query.java:427)       在org.springframework.data.jpa.repository.query.JpaQueryExecution $ CollectionExecution.doExecute(JpaQueryExecution.java:119)       在org.springframework.data.jpa.repository.query.JpaQueryExecution.execute(JpaQueryExecution.java:83)       在org.springframework.data.jpa.repository.query.AbstractJpaQuery.doExecute(AbstractJpaQuery.java:116)       在org.springframework.data.jpa.repository.query.AbstractJpaQuery.execute(AbstractJpaQuery.java:106)       at org.springframework.data.repository.core.support.RepositoryFactorySupport $ QueryExecutorMethodInterceptor.doInvoke(RepositoryFactorySupport.java:476)       at org.springframework.data.repository.core.support.RepositoryFactorySupport $ QueryExecutorMethodInterceptor.invoke(RepositoryFactorySupport.java:460)       在org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179)       在org.springframework.data.projection.DefaultMethodInvokingMethodInterceptor.invoke(DefaultMethodInvokingMethodInterceptor.java:61)       在org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179)       at org.springframework.transaction.interceptor.TransactionInterceptor $ 1.proceedWithInvocation(TransactionInterceptor.java:99)       at org.springframework.transaction.interceptor.TransactionAspectSupport.invokeWithinTransaction(TransactionAspectSupport.java:282)       at org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:96)       在org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179)       at org.springframework.dao.support.PersistenceExceptionTranslationInterceptor.invoke(PersistenceExceptionTranslationInterceptor.java:136)       ......还有8个   引起:com.mysql.jdbc.exceptions.jdbc4.MySQLSyntaxErrorException:每个派生表必须有自己的别名       at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)       at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:62)       at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45)       at java.lang.reflect.Constructor.newInstance(Constructor.java:423)       在com.mysql.jdbc.Util.handleNewInstance(Util.java:409)       在com.mysql.jdbc.Util.getInstance(Util.java:384)       在com.mysql.jdbc.SQLError.createSQLException(SQLError.java:1054)       在com.mysql.jdbc.MysqlIO.checkErrorPacket(MysqlIO.java:3566)       在com.mysql.jdbc.MysqlIO.checkErrorPacket(MysqlIO.java:3498)       在com.mysql.jdbc.MysqlIO.sendCommand(MysqlIO.java:1959)       在com.mysql.jdbc.MysqlIO.sqlQueryDirect(MysqlIO.java:2113)       在com.mysql.jdbc.ConnectionImpl.execSQL(ConnectionImpl.java:2568)       在com.mysql.jdbc.PreparedStatement.executeInternal(PreparedStatement.java:2113)       在com.mysql.jdbc.PreparedStatement.executeQuery(PreparedStatement.java:2275)       在com.zaxxer.hikari.pool.ProxyPreparedStatement.executeQuery(ProxyPreparedStatement.java:52)       在com.zaxxer.hikari.pool.HikariProxyPreparedStatement.executeQuery(HikariProxyPreparedStatement.java)       at org.hibernate.engine.jdbc.internal.ResultSetReturnImpl.extract(ResultSetReturnImpl.java:70)       ......还有38个   块引用

[UPDATE] 我找到了导致问题的代码。 sql作为右选择语句进入,但随后使用oracle方言执行子查询。 它在类org.hibernate.loader.Loader(http://docs.jboss.org/hibernate/orm/4.1/javadocs/index.html?org/hibernate/loader/Loader.html

进来了 从表格中选择blah_0.id,blah_0.peropty,其中property = value但是后来变成select * from(select blah_0.id,blah_0.peropty from table blah where property = value)其中rownum> = 10

    protected SqlStatementWrapper executeQueryStatement(
        String sqlStatement,
        QueryParameters queryParameters,
        boolean scroll,
        List<AfterLoadAction> afterLoadActions,
        SharedSessionContractImplementor session) throws SQLException {

    // Processing query filters.
    queryParameters.processFilters( sqlStatement, session );

    // Applying LIMIT clause.
    final LimitHandler limitHandler = getLimitHandler(
            queryParameters.getRowSelection()
    );
    String sql = limitHandler.processSql( queryParameters.getFilteredSQL(), queryParameters.getRowSelection() );

    // Adding locks and comments.
    sql = preprocessSQL( sql, queryParameters, getFactory().getDialect(), afterLoadActions );

    final PreparedStatement st = prepareQueryStatement( sql, queryParameters, limitHandler, scroll, session );
    return new SqlStatementWrapper(
            st, getResultSet(
            st,
            queryParameters.getRowSelection(),
            limitHandler,
            queryParameters.hasAutoDiscoverScalarTypes(),
            session
    )
    );
}

也许创造一种新的方言?我似乎无法使用hibernate供应商适配器,因为它只是去了oracle。

2 个答案:

答案 0 :(得分:1)

我需要设置MySQL5Dialect以生成正确的查询。总是简单的配置。

    LocalContainerEntityManagerFactoryBean lcemfb = EntityManagerFactory(merlinDataSource(),
            new String[]{"packages.to.be.scaned"});
    Properties props = new Properties();
    props.setProperty("hibernate.dialect", "org.hibernate.dialect.MySQL5Dialect");
    props.setProperty("hibernate.show_sql", String.valueOf(showQueies));
    lcemfb.setJpaProperties(props);

答案 1 :(得分:0)

你可以让你的方法返回List<>而不是Page<>,就像我相信它会避免触发计数查询一样。

它只会限制查询只查找给定范围的实体

http://docs.spring.io/spring-data/jpa/docs/1.4.2.RELEASE/reference/html/repositories.html#repositories.special-parameters