In my use case I need to pass a parameter of type List<>
, but this parameter needs to be optional and I'm having trouble implementing it, can you help me?
Endpoint:
http://localhost:8080/api/v1/census-population/find?state=1,2
it's work: required parameter
@Query(value = "SELECT s.id, s.code, s.name, s.uf, "
"SUM(cp.population) AS statePopulation, "
"COUNT(cp.id) AS countCities "
"FROM census_population cp "
"INNER JOIN cities c ON c.id = cp.city_id "
"INNER JOIN states s ON s.id = c.state_id "
"WHERE s.id IN (:state) "
"GROUP BY s.code, s.name, s.uf"
, nativeQuery = true)
List<CensusStateStats> censusByStateList(@Param("state") List<Long> state);
Result:
[
{
"id": 1,
"code": 11,
"name": "Rondônia",
"statePopulation": 1815278,
"countCities": 52
},
{
"id": 2,
"code": 12,
"name": "Acre",
"statePopulation": 906876,
"countCities": 22
}
]
it's doesn't work: optional parameter
@Query(value = "SELECT s.id, s.code, s.name, s.uf, "
"SUM(cp.population) AS statePopulation, "
"COUNT(cp.id) AS countCities "
"FROM census_population cp "
"INNER JOIN cities c ON c.id = cp.city_id "
"INNER JOIN states s ON s.id = c.state_id "
"WHERE (:state IS NULL OR s.id IN (:state)) "
"GROUP BY s.code, s.name, s.uf"
, nativeQuery = true)
List<CensusStateStats> censusByStateList(@Param("state") List<Long> state);
Result:
{
"timestamp": "2022-02-24T19:49:28.895 00:00",
"status": 500,
"error": "Internal Server Error",
"trace": "org.springframework.dao.DataIntegrityViolationException: could not extract ResultSet; SQL [n/a]; nested exception is org.hibernate.exception.DataException: could not extract ResultSet\r\n\tat org.springframework.orm.jpa.vendor.HibernateJpaDialect.convertHibernateAccessException(HibernateJpaDialect.java:280)\r\n\tat org.springframework.orm.jpa.vendor.HibernateJpaDialect.translateExceptionIfPossible(HibernateJpaDialect.java:233)\r\n\tat org.springframework.orm.jpa.AbstractEntityManagerFactoryBean.translateExceptionIfPossible(AbstractEntityManagerFactoryBean.java:551)\r\n\tat org.springframework.dao.support.ChainedPersistenceExceptionTranslator.translateExceptionIfPossible(ChainedPersistenceExceptionTranslator.java:61)\r\n\tat org.springframework.dao.support.DataAccessUtils.translateIfNecessary(DataAccessUtils.java:242)\r\n\tat org.springframework.dao.support.PersistenceExceptionTranslationInterceptor.invoke(PersistenceExceptionTranslationInterceptor.java:152)\r\n\tat org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186)\r\n\tat org.springframework.data.jpa.repository.support.CrudMethodMetadataPostProcessor$CrudMethodMetadataPopulatingMethodInterceptor.invoke(CrudMethodMetadataPostProcessor.java:145)\r\n\tat org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186)\r\n\tat org.springframework.aop.interceptor.ExposeInvocationInterceptor.invoke(ExposeInvocationInterceptor.java:97)\r\n\tat org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186)\r\n\tat org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:215)\r\n\tat com.sun.proxy.$Proxy109.censusByStateList(Unknown Source)\r\n\tat com.example.demo.service.CensusPopulationService.censusByStateList(CensusPopulationService.java:27)\r\n\tat com.example.demo.controller.CensusPopulationController.censusByStateList(CensusPopulationController.java:38)\r\n\tat java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)\r\n\tat java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)\r\n\tat java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)\r\n\tat java.base/java.lang.reflect.Method.invoke(Method.java:566)\r\n\tat org.springframework.web.method.support.InvocableHandlerMethod.doInvoke(InvocableHandlerMethod.java:205)\r\n\tat org.springframework.web.method.support.InvocableHandlerMethod.invokeForRequest(InvocableHandlerMethod.java:150)\r\n\tat org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod.invokeAndHandle(ServletInvocableHandlerMethod.java:117)\r\n\tat org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.invokeHandlerMethod(RequestMappingHandlerAdapter.java:895)\r\n\tat org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.handleInternal(RequestMappingHandlerAdapter.java:808)\r\n\tat org.springframework.web.servlet.mvc.method.AbstractHandlerMethodAdapter.handle(AbstractHandlerMethodAdapter.java:87)\r\n\tat org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:1067)\r\n\tat org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:963)\r\n\tat org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:1006)\r\n\tat org.springframework.web.servlet.FrameworkServlet.doGet(FrameworkServlet.java:898)\r\n\tat javax.servlet.http.HttpServlet.service(HttpServlet.java:655)\r\n\tat org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:883)\r\n\tat javax.servlet.http.HttpServlet.service(HttpServlet.java:764)\r\n\tat org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:227)\r\n\tat org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:162)\r\n\tat org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:53)\r\n\tat org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:189)\r\n\tat org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:162)\r\n\tat org.springframework.web.filter.RequestContextFilter.doFilterInternal(RequestContextFilter.java:100)\r\n\tat org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:119)\r\n\tat org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:189)\r\n\tat org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:162)\r\n\tat org.springframework.web.filter.FormContentFilter.doFilterInternal(FormContentFilter.java:93)\r\n\tat org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:119)\r\n\tat org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:189)\r\n\tat org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:162)\r\n\tat org.springframework.web.filter.CharacterEncodingFilter.doFilterInternal(CharacterEncodingFilter.java:201)\r\n\tat org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:119)\r\n\tat org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:189)\r\n\tat org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:162)\r\n\tat org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:197)\r\n\tat org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:97)\r\n\tat org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:540)\r\n\tat org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:135)\r\n\tat org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:92)\r\n\tat org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:78)\r\n\tat org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:357)\r\n\tat org.apache.coyote.http11.Http11Processor.service(Http11Processor.java:382)\r\n\tat org.apache.coyote.AbstractProcessorLight.process(AbstractProcessorLight.java:65)\r\n\tat org.apache.coyote.AbstractProtocol$ConnectionHandler.process(AbstractProtocol.java:895)\r\n\tat org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1722)\r\n\tat org.apache.tomcat.util.net.SocketProcessorBase.run(SocketProcessorBase.java:49)\r\n\tat org.apache.tomcat.util.threads.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1191)\r\n\tat org.apache.tomcat.util.threads.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:659)\r\n\tat org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61)\r\n\tat java.base/java.lang.Thread.run(Thread.java:829)\r\nCaused by: org.hibernate.exception.DataException: could not extract ResultSet\r\n\tat org.hibernate.exception.internal.SQLExceptionTypeDelegate.convert(SQLExceptionTypeDelegate.java:52)\r\n\tat org.hibernate.exception.internal.StandardSQLExceptionConverter.convert(StandardSQLExceptionConverter.java:37)\r\n\tat org.hibernate.engine.jdbc.spi.SqlExceptionHelper.convert(SqlExceptionHelper.java:113)\r\n\tat org.hibernate.engine.jdbc.spi.SqlExceptionHelper.convert(SqlExceptionHelper.java:99)\r\n\tat org.hibernate.engine.jdbc.internal.ResultSetReturnImpl.extract(ResultSetReturnImpl.java:67)\r\n\tat org.hibernate.loader.Loader.getResultSet(Loader.java:2322)\r\n\tat org.hibernate.loader.Loader.executeQueryStatement(Loader.java:2075)\r\n\tat org.hibernate.loader.Loader.executeQueryStatement(Loader.java:2037)\r\n\tat org.hibernate.loader.Loader.doQuery(Loader.java:956)\r\n\tat org.hibernate.loader.Loader.doQueryAndInitializeNonLazyCollections(Loader.java:357)\r\n\tat org.hibernate.loader.Loader.doList(Loader.java:2868)\r\n\tat org.hibernate.loader.Loader.doList(Loader.java:2850)\r\n\tat org.hibernate.loader.Loader.listIgnoreQueryCache(Loader.java:2682)\r\n\tat org.hibernate.loader.Loader.list(Loader.java:2677)\r\n\tat org.hibernate.loader.custom.CustomLoader.list(CustomLoader.java:338)\r\n\tat org.hibernate.internal.SessionImpl.listCustomQuery(SessionImpl.java:2195)\r\n\tat org.hibernate.internal.AbstractSharedSessionContract.list(AbstractSharedSessionContract.java:1190)\r\n\tat org.hibernate.query.internal.NativeQueryImpl.doList(NativeQueryImpl.java:177)\r\n\tat org.hibernate.query.internal.AbstractProducedQuery.list(AbstractProducedQuery.java:1617)\r\n\tat org.hibernate.query.Query.getResultList(Query.java:165)\r\n\tat org.springframework.data.jpa.repository.query.JpaQueryExecution$CollectionExecution.doExecute(JpaQueryExecution.java:128)\r\n\tat org.springframework.data.jpa.repository.query.JpaQueryExecution.execute(JpaQueryExecution.java:90)\r\n\tat org.springframework.data.jpa.repository.query.AbstractJpaQuery.doExecute(AbstractJpaQuery.java:155)\r\n\tat org.springframework.data.jpa.repository.query.AbstractJpaQuery.execute(AbstractJpaQuery.java:143)\r\n\tat org.springframework.data.repository.core.support.RepositoryMethodInvoker.doInvoke(RepositoryMethodInvoker.java:137)\r\n\tat org.springframework.data.repository.core.support.RepositoryMethodInvoker.invoke(RepositoryMethodInvoker.java:121)\r\n\tat org.springframework.data.repository.core.support.QueryExecutorMethodInterceptor.doInvoke(QueryExecutorMethodInterceptor.java:159)\r\n\tat org.springframework.data.repository.core.support.QueryExecutorMethodInterceptor.invoke(QueryExecutorMethodInterceptor.java:138)\r\n\tat org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186)\r\n\tat org.springframework.data.projection.DefaultMethodInvokingMethodInterceptor.invoke(DefaultMethodInvokingMethodInterceptor.java:80)\r\n\tat org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186)\r\n\tat org.springframework.transaction.interceptor.TransactionInterceptor$1.proceedWithInvocation(TransactionInterceptor.java:123)\r\n\tat org.springframework.transaction.interceptor.TransactionAspectSupport.invokeWithinTransaction(TransactionAspectSupport.java:388)\r\n\tat org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:119)\r\n\tat org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186)\r\n\tat org.springframework.dao.support.PersistenceExceptionTranslationInterceptor.invoke(PersistenceExceptionTranslationInterceptor.java:137)\r\n\t... 59 more\r\nCaused by: org.h2.jdbc.JdbcSQLDataException: Data conversion error converting \"ROW (1, TRUE)\"; SQL statement:\nSELECT s.id, s.code, s.name, s.uf, SUM(cp.population) AS statePopulation, COUNT(cp.id) AS countCities, FROM census_population cp INNER JOIN cities c ON c.id = cp.city_id INNER JOIN states s ON s.id = c.state_id WHERE (?, ? IS NULL OR s.id IN (?, ?)) GROUP BY s.code, s.name, s.uf [22018-200]\r\n\tat org.h2.message.DbException.getJdbcSQLException(DbException.java:457)\r\n\tat org.h2.message.DbException.getJdbcSQLException(DbException.java:429)\r\n\tat org.h2.message.DbException.get(DbException.java:194)\r\n\tat org.h2.value.Value.convertTo(Value.java:875)\r\n\tat org.h2.value.Value.convertTo(Value.java:737)\r\n\tat org.h2.value.Value.getBoolean(Value.java:561)\r\n\tat org.h2.expression.condition.ConditionAndOr.getValue(ConditionAndOr.java:101)\r\n\tat org.h2.expression.Expression.getBooleanValue(Expression.java:258)\r\n\tat org.h2.command.dml.Select.isConditionMet(Select.java:448)\r\n\tat org.h2.command.dml.Select.gatherGroup(Select.java:522)\r\n\tat org.h2.command.dml.Select.queryGroup(Select.java:487)\r\n\tat org.h2.command.dml.Select.queryWithoutCache(Select.java:839)\r\n\tat org.h2.command.dml.Query.queryWithoutCacheLazyCheck(Query.java:201)\r\n\tat org.h2.command.dml.Query.query(Query.java:489)\r\n\tat org.h2.command.dml.Query.query(Query.java:451)\r\n\tat org.h2.command.CommandContainer.query(CommandContainer.java:285)\r\n\tat org.h2.command.Command.executeQuery(Command.java:195)\r\n\tat org.h2.jdbc.JdbcPreparedStatement.executeQuery(JdbcPreparedStatement.java:114)\r\n\tat com.zaxxer.hikari.pool.ProxyPreparedStatement.executeQuery(ProxyPreparedStatement.java:52)\r\n\tat com.zaxxer.hikari.pool.HikariProxyPreparedStatement.executeQuery(HikariProxyPreparedStatement.java)\r\n\tat org.hibernate.engine.jdbc.internal.ResultSetReturnImpl.extract(ResultSetReturnImpl.java:57)\r\n\t... 90 more\r\nCaused by: java.lang.NumberFormatException: Character R is neither a decimal digit number, decimal point, nor \"e\" notation exponential mark.\r\n\tat java.base/java.math.BigDecimal.<init>(BigDecimal.java:518)\r\n\tat java.base/java.math.BigDecimal.<init>(BigDecimal.java:401)\r\n\tat java.base/java.math.BigDecimal.<init>(BigDecimal.java:834)\r\n\tat org.h2.value.Value.convertToBoolean(Value.java:908)\r\n\tat org.h2.value.Value.convertTo(Value.java:800)\r\n\t... 107 more\r\n",
"message": "could not extract ResultSet; SQL [n/a]; nested exception is org.hibernate.exception.DataException: could not extract ResultSet",
"path": "/api/v1/census-population/find"
}
My classes:
MODELS
State
package com.example.demo.model;
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
import javax.persistence.*;
@Entity
@Data
@Builder
@AllArgsConstructor
@NoArgsConstructor
@Table(name = "states")
@JsonIgnoreProperties({"hibernateLazyInitializer", "handler"})
public class State {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
private Integer code;
private String name;
@Column(length = 2)
private String uf;
}
City
package com.example.demo.model;
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
import javax.persistence.*;
@Entity
@Data
@Builder
@AllArgsConstructor
@NoArgsConstructor
@Table(name = "cities")
@JsonIgnoreProperties({"hibernateLazyInitializer", "handler"})
public class City {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "state_id", nullable = false, foreignKey = @ForeignKey(name = "fk_cities_states1"))
private State state;
private String code;
private String name;
}
Cencus
package com.example.demo.model;
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
import javax.persistence.*;
@Entity
@Data
@Builder
@AllArgsConstructor
@NoArgsConstructor
@Table(name = "census")
@JsonIgnoreProperties({"hibernateLazyInitializer", "handler"})
public class Census {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
private String name;
}
CensusPopulation
package com.example.demo.model;
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
import javax.persistence.*;
@Entity
@Data
@Builder
@AllArgsConstructor
@NoArgsConstructor
@Table(name = "census")
@JsonIgnoreProperties({"hibernateLazyInitializer", "handler"})
public class Census {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
private String name;
}
DTO
CensusStateStats
package com.example.demo.dto;
public interface CensusStateStats {
Long getId();
Integer getCode();
String getName();
Long getStatePopulation();
Long getCountCities();
}
REPOSITORY
CensusPopulationRep
package com.example.demo.repository;
import com.example.demo.dto.CensusStateCitiesStats;
import com.example.demo.dto.CensusStateStats;
import com.example.demo.model.CensusPopulation;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.Query;
import org.springframework.data.repository.query.Param;
import java.util.List;
public interface CensusPopulationRep extends JpaRepository<CensusPopulation, Long> {
@Query(value = "SELECT s.id, s.code, s.name, s.uf, "
"SUM(cp.population) AS statePopulation, "
"COUNT(cp.id) AS countCities "
"FROM census_population cp "
"INNER JOIN cities c ON c.id = cp.city_id "
"INNER JOIN states s ON s.id = c.state_id "
"WHERE (:state IS NULL OR s.id IN (:state)) "
"GROUP BY s.code, s.name, s.uf"
, nativeQuery = true)
List<CensusStateStats> censusByStateList(@Param("state") List<Long> state);
}
SERVICE
CensusPopulationService
package com.example.demo.service;
import com.example.demo.dto.CensusStateCitiesStats;
import com.example.demo.dto.CensusStateStats;
import com.example.demo.model.CensusPopulation;
import com.example.demo.repository.CensusPopulationRep;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;
import java.util.List;
@Service
@RequiredArgsConstructor
public class CensusPopulationService {
private final CensusPopulationRep censusPopulationRep;
public List<CensusStateStats> censusByStateList(List<Long> state) {
return censusPopulationRep.censusByStateList(state);
}
}
CONTROLLER
CensusPopulationController
package com.example.demo.controller;
import com.example.demo.dto.*;
import com.example.demo.model.CensusPopulation;
import com.example.demo.service.CensusPopulationService;
import lombok.RequiredArgsConstructor;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;
@RestController
@RequestMapping("api/v1/census-population")
@RequiredArgsConstructor
public class CensusPopulationController {
private final CensusPopulationService censusPopulationService;
@GetMapping("/find")
public ResponseEntity<List<CensusStateStatsDto>> censusByStateList(@RequestParam(required = false) List<Long> state) {
return ResponseEntity.ok(censusPopulationService.censusByStateList(state).stream()
.map(CensusStateStatsDto::new)
.collect(Collectors.toList()));
}
}
CodePudding user response:
Assuming the values (1,2) are going in your (:state), it would look like this: WHERE (1,2 IS NULL OR s.id IN(1,2))
Please review this code which should resolve your issue.
Ex: WHERE ((:state) IS NULL OR s.id IN (:state))