Spring Boot JPA查询多行LocalDate失败,单行正常:无可用转换器
Spring Boot 3.3.0中JPA多行LocalDate查询失败问题
JPA 2.2原生支持Java 8的LocalDate类型,但在Spring Boot 3.3.0版本下,使用原生SQL查询单行LocalDate数据时正常,查询多行却无法完成类型转换,抛出转换器找不到的异常。
错误日志
org.springframework.core.convert.ConversionFailedException: Failed to convert from type [java.util.ArrayList<?>] to type [@org.springframework.data.jpa.repository.Query java.util.List<java.time.LocalDate>] for value [[...]] Caused by: org.springframework.core.convert.ConverterNotFoundException: No converter found capable of converting from type [java.sql.Date] to type [@org.springframework.data.jpa.repository.Query java.time.LocalDate] at org.springframework.core.convert.support.GenericConversionService.handleConverterNotFound(GenericConversionService.java:294)
相关代码
TestEntity.java
@Entity public class TestEntity { @Id @GeneratedValue(strategy = GenerationType.AUTO) @Column(name = "id") private Long id; @Column(name = "TEST_DATE", columnDefinition = "DATE") private LocalDate testDate; // 省略Setter和Getter方法 }
单行查询仓库(正常运行)
public interface TestRepository extends CrudRepository<TestEntity, Long> { @Query(value = "SELECT TEST_DATE FROM TEST_ENTITY", nativeQuery = true) LocalDate findBy(); }
多行查询仓库(执行失败)
public interface TestRepositoryList extends CrudRepository<TestEntity, Long> { @Query(value = "SELECT TEST_DATE FROM TEST_ENTITY", nativeQuery = true) List<LocalDate> findBy(); }
测试代码
// 正常运行的单行查询测试 @Test void testFindBySingle() throws InterruptedException { testRepository.save(new TestEntity(1L, LocalDate.now())); log.info(String.valueOf(testRepository.findBy())); } // 执行失败的多行查询测试 @Test void testFindByList() { testRepositoryList.save(new TestEntity(1L, LocalDate.now())); testRepositoryList.save(new TestEntity(2L, LocalDate.now())); log.info(String.valueOf(testRepositoryList.findBy())); }
解决方案
方案1:改用JPQL查询
放弃原生SQL,使用JPQL让JPA自动处理类型映射,这是最推荐的方式:
public interface TestRepositoryList extends CrudRepository<TestEntity, Long> { @Query("SELECT t.testDate FROM TestEntity t") List<LocalDate> findBy(); }
方案2:注册自定义类型转换器
如果必须使用原生SQL,可以添加自定义转换器处理java.sql.Date到LocalDate的转换:
- 创建转换器类:
import org.springframework.core.convert.converter.Converter; import org.springframework.stereotype.Component; import java.sql.Date; import java.time.LocalDate; @Component public class SqlDateToLocalDateConverter implements Converter<Date, LocalDate> { @Override public LocalDate convert(Date source) { return source != null ? source.toLocalDate() : null; } }
- 配置转换器(若Spring未自动扫描到,可手动注册):
import org.springframework.context.annotation.Configuration; import org.springframework.format.FormatterRegistry; import org.springframework.web.servlet.config.annotation.WebMvcConfigurer; @Configuration public class WebConfig implements WebMvcConfigurer { @Override public void addFormatters(FormatterRegistry registry) { registry.addConverter(new SqlDateToLocalDateConverter()); } }
方案3:数据库端显式转换(依赖数据库类型)
针对特定数据库,在原生SQL中显式转换日期格式,例如MySQL:
@Query(value = "SELECT CAST(TEST_DATE AS DATE) FROM TEST_ENTITY", nativeQuery = true) List<LocalDate> findBy();
内容的提问来源于stack exchange,提问作者Justus5324
相关产品推荐
相关产品推荐

