Custom class is registered as simple type only if there is writing converter
I am using Spring Data JDBC repository to query data for report (hence, readonly). In one place I needed to convert from JSONB to a DTO. I registered a customer converter marked as @ReadingConverter for that purpose, but for some reason it was never called. Debugging the code, I noticed that my DTO is considered as an entity, although it should have been registered as a simple type. Debugging more I found out that only the source type of a @WritingConverter is registered as a simple type. Adding a dummy writing converter fixed the issue for me. However, this seems unexpected and the fix adds redundant code.
My code:
@Data
public class ReportDTO {
private MyData myData;
}
@Configuration
public class JdbcConfig extends AbstractJdbcConfiguration
private final ObjectMapper objectMapper = new ObjectMapper();
@Bean
@NonNull
@Override
public JdbcCustomConversions jdbcCustomConversions() {
return new JdbcCustomConversions(
List.of(
new JsonbToMyData(objectMapper),
)
);
}
@ReadingConverter
@RequiredArgsConstructor
static class JsonbToMyData implements Converter<PGobject, MyData> {
private final ObjectMapper objectMapper;
@Override
public MyData convert(PGobject source) {
try {
return objectMapper.readValue(source.getValue(), MyData.class);
} catch (JsonProcessingException e) {
throw new RuntimeException(e);
}
}
}
The behaviour you describe is a bug and should get fixed. The type should NOT be considered a simple type, but custom conversions should be taken into consideration before treating it as an entity.
The type should NOT be considered a simple type
But all source types of writing converters always add to custom simple types. Moreover, all custom types in BasicRelationalConverter are treated as simple:
if (converterRegistration.isWriting()) {
writingPairs.add(pair);
customSimpleTypes.add(pair.getSourceType()); // <<<<<<<<<<<<<<<<<<<<
if (logger.isWarnEnabled() && !converterRegistration.isSimpleTargetType()) {
logger.warn(String.format(WRITE_CONVERTER_NOT_SIMPLE, pair.getSourceType(), pair.getTargetType()));
}
}
Custom simple types is Set<Class<?>>.
Why not just add this type when registering a converter for reading? The simple types set will not contain repetitions.