with stored namedstoredprocedurequery data con java jpa spring-data spring-data-jpa

java - stored - spring data jpa jpql



¿Cómo devolver un solo resultado de Spring-Data-JPA? (2)

Estoy tratando de obtener un solo resultado de una consulta de Spring Data. Estoy buscando devolver la identificación más grande de una tabla de usuario. Esperaba que fuera sencillo, pero estoy un poco perdido.

Hasta ahora, con base en esta publicación SO relacionada , he llegado a la conclusión de que necesito usar una Specification para definir mi consulta y resultados de Page d, especificando la cantidad de resultados que deseo recuperar. Lamentablemente, recibo una excepción de acceso a datos HibernateJdbcException .

Mi Specification / Predicate se supone que es bastante simple y refleja: from User order by id :

Page<User> result =userRepository.findAll(new Specification<User>() { @Override public Predicate toPredicate(Root<User> root, CriteriaQuery<?> query, CriteriaBuilder cb) { query.orderBy(cb.desc(root.get("id"))); return query.getRestriction(); } }, new PageRequest(0, 10)); MatcherAssert.assertThat(result.isFirstPage(), is(true)); User u = result.getContent().get(0);

Excepción lanzada:

org.springframework.orm.hibernate3.HibernateJdbcException: JDBC exception on Hibernate data access: SQLException for SQL [n/a]; SQL state [90016]; error code [90016]; could not extract ResultSet; nested exception is org.hibernate.exception.GenericJDBCException: could not extract ResultSet at org.springframework.orm.hibernate3.SessionFactoryUtils.convertHibernateAccessException(SessionFactoryUtils.java:651) at org.springframework.orm.jpa.vendor.HibernateJpaDialect.translateExceptionIfPossible(HibernateJpaDialect.java:106) at org.springframework.orm.jpa.AbstractEntityManagerFactoryBean.translateExceptionIfPossible(AbstractEntityManagerFactoryBean.java:403) at org.springframework.dao.support.ChainedPersistenceExceptionTranslator.translateExceptionIfPossible(ChainedPersistenceExceptionTranslator.java:58) at org.springframework.dao.support.DataAccessUtils.translateIfNecessary(DataAccessUtils.java:213) at org.springframework.dao.support.PersistenceExceptionTranslationInterceptor.invoke(PersistenceExceptionTranslationInterceptor.java:163) at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:172) at org.springframework.data.jpa.repository.support.LockModeRepositoryPostProcessor$LockModePopulatingMethodIntercceptor.invoke(LockModeRepositoryPostProcessor.java:92) ... ... Caused by: org.hibernate.exception.GenericJDBCException: could not extract ResultSet at org.hibernate.exception.internal.StandardSQLExceptionConverter.convert(StandardSQLExceptionConverter.java:54) at org.hibernate.engine.jdbc.spi.SqlExceptionHelper.convert(SqlExceptionHelper.java:126) at org.hibernate.engine.jdbc.spi.SqlExceptionHelper.convert(SqlExceptionHelper.java:112) at org.hibernate.engine.jdbc.internal.ResultSetReturnImpl.extract(ResultSetReturnImpl.java:89) at org.hibernate.loader.Loader.getResultSet(Loader.java:2065) at org.hibernate.loader.Loader.executeQueryStatement(Loader.java:1862) at org.hibernate.loader.Loader.executeQueryStatement(Loader.java:1838) at org.hibernate.loader.Loader.doQuery(Loader.java:909) at org.hibernate.loader.Loader.doQueryAndInitializeNonLazyCollections(Loader.java:354) at org.hibernate.loader.Loader.doList(Loader.java:2553) at org.hibernate.loader.Loader.doList(Loader.java:2539) at org.hibernate.loader.Loader.listIgnoreQueryCache(Loader.java:2369) at org.hibernate.loader.Loader.list(Loader.java:2364) at org.hibernate.loader.hql.QueryLoader.list(QueryLoader.java:496) at org.hibernate.hql.internal.ast.QueryTranslatorImpl.list(QueryTranslatorImpl.java:387) at org.hibernate.engine.query.spi.HQLQueryPlan.performList(HQLQueryPlan.java:231) at org.hibernate.internal.SessionImpl.list(SessionImpl.java:1264) at org.hibernate.internal.QueryImpl.list(QueryImpl.java:103) at org.hibernate.jpa.internal.QueryImpl.list(QueryImpl.java:573) at org.hibernate.jpa.internal.QueryImpl.getResultList(QueryImpl.java:449) at org.hibernate.jpa.criteria.compile.CriteriaQueryTypeQueryAdapter.getResultList(CriteriaQueryTypeQueryAdapter.java:67) at org.springframework.data.jpa.repository.query.QueryUtils.executeCountQuery(QueryUtils.java:406) at org.springframework.data.jpa.repository.support.SimpleJpaRepository.readPage(SimpleJpaRepository.java:433) at org.springframework.data.jpa.repository.support.SimpleJpaRepository.findAll(SimpleJpaRepository.java:332) 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:606) at org.springframework.data.repository.core.support.RepositoryFactorySupport$QueryExecutorMethodInterceptor.executeMethodOn(RepositoryFactorySupport.java:358) at org.springframework.data.repository.core.support.RepositoryFactorySupport$QueryExecutorMethodInterceptor.invoke(RepositoryFactorySupport.java:343) at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:172) 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.dao.support.PersistenceExceptionTranslationInterceptor.invoke(PersistenceExceptionTranslationInterceptor.java:155) ... 46 more Caused by: org.h2.jdbc.JdbcSQLException: Column "USER1_.ID" must be in the GROUP BY list; SQL statement: /* select count(generatedAlias0) from User as generatedAlias0, User as generatedAlias1 where 1=1 order by generatedAlias1.id desc */ select count(user0_.id) as col_0_0_ from user user0_ cross join user user1_ where 1=1 order by user1_.id desc [90016-173] at org.h2.message.DbException.getJdbcSQLException(DbException.java:331) at org.h2.message.DbException.get(DbException.java:171) at org.h2.message.DbException.get(DbException.java:148) at org.h2.expression.ExpressionColumn.updateAggregate(ExpressionColumn.java:166) at org.h2.command.dml.Select.queryGroup(Select.java:344) at org.h2.command.dml.Select.queryWithoutCache(Select.java:620) at org.h2.command.dml.Query.query(Query.java:314) at org.h2.command.dml.Query.query(Query.java:284) at org.h2.command.dml.Query.query(Query.java:36) at org.h2.command.CommandContainer.query(CommandContainer.java:91) at org.h2.command.Command.executeQuery(Command.java:195) at org.h2.jdbc.JdbcPreparedStatement.executeQuery(JdbcPreparedStatement.java:106) at org.hibernate.engine.jdbc.internal.ResultSetReturnImpl.extract(ResultSetReturnImpl.java:80) ... 78 more

Estoy un poco perdido por el error de Hibernate, está pidiendo una cláusula group . Supongo que tiene algo que ver con la forma en que he creado el predicado, pero no estoy seguro de cómo crear un predicado simple como este.

EDITAR

Tal como lo sugirió @OliverGierke, traté de eliminar la root = query.from(User.class) pero hibernate aún arroja el mismo error (habilité el rastreo completo de consultas de hibernación). Extrañamente, sin embargo, esta vez, no hay GROUP BY en el SQL generado, así que estoy aún más confundido que antes.

2014-03-18 11:59:44,475 [main] DEBUG org.hibernate.SQL - /* select count(generatedAlias0) from User as generatedAlias0 order by generatedAlias0.id desc */ select count(user0_.id) as col_0_0_ from user user0_ order by user0_.id desc Hibernate: /* select count(generatedAlias0) from User as generatedAlias0 order by generatedAlias0.id desc */ select count(user0_.id) as col_0_0_ from user user0_ order by user0_.id desc 2014-03-18 11:59:44,513 [main] WARN hibernate.engine.jdbc.spi.SqlExceptionHelper - SQL Error: 90016, SQLState: 90016 2014-03-18 11:59:44,513 [main] ERROR hibernate.engine.jdbc.spi.SqlExceptionHelper - Column "USER0_.ID" must be in the GROUP BY list; SQL statement: /* select count(generatedAlias0) from User as generatedAlias0 order by generatedAlias0.id desc */ select count(user0_.id) as col_0_0_ from user user0_ order by user0_.id desc [90016-173]


No está utilizando la root que se entrega en la instancia de Specification para invocar el .get(…) . Eso no permite que la instancia registre el id está usando y, por lo tanto, lo agrega de forma transparente al conjunto de resultados.

Simplemente eliminando root = query.from(User.class); debería hacer el truco.

Sin embargo, lo que me deja perplejo es que mencionas que tienes la intención de crear una consulta "buscar por ID". Lo que realmente está creando es un "buscar todo ordenado por id". Si es realmente lo primero que desea obtener, existe un findOne(…) predefinido de findOne(…) en CrudRepository que puede usar.

Teniendo en cuenta los comentarios a continuación, parece que lo que realmente intenta lograr es encontrar un solo usuario con la identificación más pequeña. Esto también se puede lograr simplemente extendiendo PagingAndSortingRepository y luego use un código de cliente como este:

interface UserRepository extends PagingAndSortingRepository<User, Long> { … } Page<User> users = repository.findAll(new PageRequest(0, 1, Direction.ASC, "id")); User user = users.getContent.get(0);

Esto limitará el resultado a la primera página por un tamaño de página de 1 con orden ascendente por id.


No estoy seguro de por qué está buscando una colección para obtener un solo resultado. Corrígeme si me equivoco, pero la solución a tu problema, tal como lo interpreté, es muy fácil de resolver usando @Query . Agregue lo siguiente a su interfaz de repositorio.

@Query("SELECT max(t.id) FROM #{#entityName} t") Integer getMaxId();