spring-projects / spring-data-relational

Spring Data Relational. Home of Spring Data JDBC and Spring Data R2DBC.
https://spring.io/projects/spring-data-jdbc
Apache License 2.0
740 stars 342 forks source link

Reading converter executed for 'countBy' method #1732

Closed jaeykweon closed 5 months ago

jaeykweon commented 5 months ago

Situation

While using Reading Converter for converting data, I found some query method which works in 3.2.1 but throws error in 3.2.2.

You can compare 3.2.1 and 3.2.2 in example code.

Error Description

Codes added at R2dbcEntityTemplate.java in 3.2.2 handle 'count query method' differently compared to 3.2.1.

You can see changes below or Comparing changes

// 3.2.1
if(simpleType) {
    rowMapper = dataAccessStrategy.getRowMapper(resultType);
} else {
... // else logic
}

// 3.2.2
if(converter instanceof AbstractRelationalConverter relationalConverter
    && relationalConverter.getConversions().hasCustomReadTarget(Row.class,  entityType)) {

    ConversionService conversionService = relationalConverter.getConversionService();
    rowMapper = (row, rowMetadata) -> (T) conversionService.convert(row, entityType);
} else if(simpleType) {
    rowMapper = dataAccessStrategy.getRowMapper(resultType);
} else {
... // same as 3.2.1
}

We have countByCategory(category: Category): Long for example.

In 3.2.1, R2dbcEntityTemplate checks whether return type is simple type or not at first. So query result doesn't enter ReadingConverter.

In 3.2.2 however, it checks whether custom converter exists or not before checking simple type. In this time, query result enters ReadingConverter. Query result have only one column, and error occurs.

How to test

Use example code.

Suggestion

I think switching first and second statement may solve this problem.

if(simpleType) {
    rowMapper = dataAccessStrategy.getRowMapper(resultType);
} else if(converter instanceof AbstractRelationalConverter relationalConverter
    && relationalConverter.getConversions().hasCustomReadTarget(Row.class, entityType)) {

    ConversionService conversionService = relationalConverter.getConversionService();
    rowMapper = (row, rowMetadata) -> (T) conversionService.convert(row, entityType);
} else {
... // same as 3.2.1
}

ETC

Sorry for my poor English. I hope you understand what I want to say.

mp911de commented 5 months ago

This should be fixed via #1723, care to retest against the latest 3.2.x snapshots?

jaeykweon commented 5 months ago

It works at 3.2.3-snapshot. Thank you!