Java spring / hibernate question: Query is giving me an error but I have no idea why

Viewed 147

For an assignment I am supposed to return the top 10 countries with the most airports with the count. I wrote an app with Spring Boot and tried many different ways, but I can't get it to work. My guess is that my query is not correct, but I'm not sure. I searched around on Google for a few days, but can't figure out what the problem is.

As you can see in the error, it is showing the amount of airports for every country but it cant convert an arrayList to a List??

When I run the app I get this error:

Exception in thread "restartedMain" java.lang.reflect.InvocationTargetException
    at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
    at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.base/java.lang.reflect.Method.invoke(Method.java:566)
    at org.springframework.boot.devtools.restart.RestartLauncher.run(RestartLauncher.java:49)
Caused by: org.springframework.core.convert.ConversionFailedException: Failed to convert from type [java.util.ArrayList<?>] to type [@org.springframework.data.jpa.repository.Query java.util.List<com.example.lunatech.datamodels.Airport>] for value '[1, 32, 62, 3, 1, 8, 13, 57, 24, 713, 4, 138, 1908, 1, 35, 11, 2, 16, 122, 50, 75, 2, 4, 9, 1, 3, 2, 192, 3, 3839, 63, 3, 35, 31, 20, 2454, 1, 267, 36, 50, 75, 24, 9, 474, 26, 330, 700, 124, 134, 10, 1, 1, 12, 146, 703, 9, 70, 2, 37, 62, 91, 26, 69, 3, 5, 181, 52, 106, 29, 13, 6, 8, 789, 32, 489, 3, 27, 10, 2, 8, 1, 82, 1, 14, 6, 4, 73, 49, 3, 5, 38, 9, 154, 32, 8, 64, 461, 47, 28, 3, 329, 1, 76, 135, 85, 200, 1, 24, 17, 148, 239, 50, 14, 21, 4, 2, 67, 249, 4, 8, 3, 106, 19, 4, 2, 1, 24, 15, 33, 40, 9, 24, 59, 36, 1, 8, 7, 2, 70, 33, 13, 31, 76, 29, 1, 11, 1, 21, 2, 7, 3, 9, 29, 206, 105, 40, 224, 21, 23, 1, 39, 30, 80, 162, 47, 1, 1, 205, 25, 63, 164, 54, 565, 117, 125, 170, 2, 62, 5, 71, 3, 52, 5, 2, 28, 26, 920, 7, 75, 37, 16, 31, 178, 9, 1, 33, 24, 12, 2, 14, 23, 28, 40, 2, 27, 1, 28, 16, 10, 23, 4, 7, 69, 15, 11, 21, 15, 6, 119, 3, 1, 32, 69, 137, 19, 6, 21501, 20, 174, 1, 5, 592, 3, 9, 42, 32, 2, 4, 25, 1, 445, 76, 83, 1]'; nested exception is org.springframework.core.convert.ConverterNotFoundException: No converter found capable of converting from type [java.lang.Long] to type [@org.springframework.data.jpa.repository.Query com.example.lunatech.datamodels.Airport]
    at org.springframework.core.convert.support.ConversionUtils.invokeConverter(ConversionUtils.java:47)
    at org.springframework.core.convert.support.GenericConversionService.convert(GenericConversionService.java:192)
    at org.springframework.core.convert.support.GenericConversionService.convert(GenericConversionService.java:213)
    at org.springframework.data.repository.core.support.QueryExecutionResultHandler.postProcessInvocationResult(QueryExecutionResultHandler.java:167)
    at org.springframework.data.repository.core.support.QueryExecutionResultHandler.postProcessInvocationResult(QueryExecutionResultHandler.java:77)
    at org.springframework.data.repository.core.support.QueryExecutorMethodInterceptor.invoke(QueryExecutorMethodInterceptor.java:138)
    at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186)
    at org.springframework.data.projection.DefaultMethodInvokingMethodInterceptor.invoke(DefaultMethodInvokingMethodInterceptor.java:80)
    at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186)
    at org.springframework.transaction.interceptor.TransactionInterceptor$1.proceedWithInvocation(TransactionInterceptor.java:123)
    at org.springframework.transaction.interceptor.TransactionAspectSupport.invokeWithinTransaction(TransactionAspectSupport.java:388)
    at org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:119)
    at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186)
    at org.springframework.dao.support.PersistenceExceptionTranslationInterceptor.invoke(PersistenceExceptionTranslationInterceptor.java:137)
    at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186)
    at org.springframework.data.jpa.repository.support.CrudMethodMetadataPostProcessor$CrudMethodMetadataPopulatingMethodInterceptor.invoke(CrudMethodMetadataPostProcessor.java:145)
    at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186)
    at org.springframework.aop.interceptor.ExposeInvocationInterceptor.invoke(ExposeInvocationInterceptor.java:97)
    at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186)
    at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:215)
    at com.sun.proxy.$Proxy101.countAirportByIso_country(Unknown Source)
    at com.example.lunatech.LunatechApplication.testDAO(LunatechApplication.java:34)
    at com.example.lunatech.LunatechApplication.main(LunatechApplication.java:21)
    ... 5 more
Caused by: org.springframework.core.convert.ConverterNotFoundException: No converter found capable of converting from type [java.lang.Long] to type [@org.springframework.data.jpa.repository.Query com.example.lunatech.datamodels.Airport]
    at org.springframework.core.convert.support.GenericConversionService.handleConverterNotFound(GenericConversionService.java:322)
    at org.springframework.core.convert.support.GenericConversionService.convert(GenericConversionService.java:195)
    at org.springframework.core.convert.support.CollectionToCollectionConverter.convert(CollectionToCollectionConverter.java:89)
    at org.springframework.core.convert.support.ConversionUtils.invokeConverter(ConversionUtils.java:41)
    ... 27 more

Controller:

public AirportController(AirportsService airportsService) {
    this.airportsService = airportsService;
}

@GetMapping("/top")
public ResponseEntity getCountriesWithMostAirports() {

    Optional<List<Airport>> airportList = airportsService.countriesWithMostAirports();
    if (airportList.isPresent())
        return ResponseEntity.ok(airportList.get());

    return ResponseEntity.badRequest().body("Something went wrong");
}

Datamodels:

private String iso_country;

AirportDAO:

public interface AirportDAO extends JpaRepository<Airport, Long> {
    @Query("SELECT COUNT(a) FROM Airport a GROUP BY a.iso_country ")
    List<Airport> countAirportByIso_country();
}

AirportService:

   public Optional<List<Airport>> countriesWithMostAirports(){
        List<Airport> countryList = airportDAO.countAirportByIso_country();
        return Optional.of(countryList);
    }
1 Answers

"SELECT COUNT(a) FROM Airport a GROUP BY a.iso_country " returns a list of long values not of Airport objects.

So you Dao should look like

public interface AirportDAO extends JpaRepository<Airport, Long> {
    @Query("SELECT COUNT(a) FROM Airport a GROUP BY a.iso_country ")
    List<Long> countAirportByIso_country();
}

But what you need for the assigment is the count and the name of the country if my understanding is correct. Also you result must be orderd and limited to 10 Something like:

public interface AirportDAO extends JpaRepository<Airport, Long> {
    @Query("SELECT COUNT(a),iso_country   FROM Airport a GROUP BY a.iso_country order by count(a) limit 10")
    List<Object[]> countAirportByIso_country();
}
Related