如何向JPA/Hibernate查询提供LocalDateTime?

3

我正在我的@RepositoryRestResource中构建一个查询

查询的样子如下:

@Query("Select DISTINCT comp from InsuranceCompany comp " +
            "LEFT JOIN comp.orders ord " +
            "wHERE ord.invoiced = false " +
            "and (:date is null or :date >= ord.completionTime)"
    )
public Page<InsuranceCompany> method(LocalDateTime date, Pageable pageable);

但是它会抛出以下异常。
Failed to convert from type [java.lang.String] to type [java.time.LocalDateTime] for value '2020-02-14T15:50:24'

当我使用以下内容调用端点:

GET /method?date=2020-02-14T15:50:24
3个回答

3

使用@DateTimeFormat进行标记,以便Spring正确转换它:

public Page<InsuranceCompany> method(@DateTimeFormat(iso = DateTimeFormat.ISO.DATE_TIME) LocalDateTime date, 
                                     Pageable pageable);

2

Spring默认无法将REST参数转换为LocalDateTime。您需要使用@DateTimeFormat注释在参数级别上提供日期格式的信息,或者使用DateTimeFormatterRegistrar在全局范围内提供。

本文介绍了这两种替代方案:https://www.baeldung.com/spring-date-parameters


1

选项1:为所有Spring Boot应用程序REST端点全局设置日期/时间格式

您可以全局配置Spring以使用特定的日期/日期时间格式用于您的REST端点。建议您使用默认的Jackson来处理JSON映射,您可以创建一个配置类如下所示,在其中设置格式:

@Configuration
public class DateTimeSerializationConfiguration implements Jackson2ObjectMapperBuilderCustomizer {

    private static final DateTimeFormatter DATE_FORMATTER = ISO_LOCAL_DATE;
    private static final DateTimeFormatter DATE_TIME_FORMATTER = ISO_DATE_TIME;
    private static final DateTimeFormatter TIME_FORMATTER = ofPattern("HH:mm");

    @Bean
    public Formatter<LocalDate> localDateFormatter() {
        return new Formatter<LocalDate>() {
            @Override
            public LocalDate parse(String text, Locale locale) {
                return LocalDate.parse(text, DATE_FORMATTER);
            }

            @Override
            public String print(LocalDate object, Locale locale) {
                return DATE_FORMATTER.format(object);
            }
        };
    }

    @Bean
    public Formatter<LocalDateTime> localDateTimeFormatter() {
        return new Formatter<LocalDateTime>() {
            @Override
            public LocalDateTime parse(String text, Locale locale) {
                return LocalDateTime.parse(text, DATE_TIME_FORMATTER);
            }

            @Override
            public String print(LocalDateTime object, Locale locale) {
                return DATE_TIME_FORMATTER.format(object);
            }
        };
    }

    @Bean
    public Formatter<LocalTime> localTimeFormatter() {
        return new Formatter<LocalTime>() {
            @Override
            public LocalTime parse(String text, Locale locale) {
                return LocalTime.parse(text, TIME_FORMATTER);
            }

            @Override
            public String print(LocalTime object, Locale locale) {
                return TIME_FORMATTER.format(object);
            }
        };
    }

    @Override
    public void customize(Jackson2ObjectMapperBuilder jacksonObjectMapperBuilder) {
        jacksonObjectMapperBuilder.serializers(
            new LocalDateSerializer(DATE_FORMATTER),
            new LocalDateTimeSerializer(DATE_TIME_FORMATTER),
            new LocalTimeSerializer(TIME_FORMATTER));
        jacksonObjectMapperBuilder.deserializers(
            new LocalDateDeserializer(DATE_FORMATTER),
            new LocalDateTimeDeserializer(DATE_TIME_FORMATTER),
            new LocalTimeDeserializer(TIME_FORMATTER));
    }

}


然后,您可以创建像这样的控制器方法:
@RestController
public class BookingController {

    private final YourService yourService;

    @Autowired
    public BookingController(YourService yourService) {
        this.yourService = yourService;
    }

    @GetMapping("/your/api/endpoint")
    public YourObject yourControllerMethod(@RequestParam LocalDate date, Pageable pageable) {
        return yourService.yourServiceMethod(date, pageable);
    }

    // Or: with LocalDateTime

    @GetMapping("/your/api/endpoint")
    public YourObject yourControllerMethod(@RequestParam LocalDateTime dateTime, Pageable pageable) {
        return yourService.yourServiceMethod(dateTime, pageable);
    }
}

选项2:单独为每个REST端点设置日期/时间格式

如果您喜欢单独为每个端点设置格式,则必须使用@DateTimeFormat注释请求参数并指定期望的格式。下面的示例显示了如何完成不同的示例:

@RestController
public class BookingController {

    private final YourService yourService;

    @Autowired
    public BookingController(YourService yourService) {
        this.yourService = yourService;
    }

    @GetMapping("/your/api/endpoint")
    public YourObject yourControllerMethod(@RequestParam @DateTimeFormat(iso = DateTimeFormat.ISO.DATE) LocalDate date, Pageable pageable) {
        return yourService.yourServiceMethod(date, pageable);
    }

    // Or: with LocalDateTime

    @GetMapping("/your/api/endpoint")
    public YourObject yourControllerMethod(@RequestParam @DateTimeFormat(iso = DateTimeFormat.ISO.DATE_TIME) LocalDateTime dateTime, Pageable pageable) {
        return yourService.yourServiceMethod(dateTime, pageable);
    }

    // Or: with your custom pattern

    @GetMapping("/your/api/endpoint")
    public YourObject yourControllerMethod(@RequestParam @DateTimeFormat(pattern = "dd.MM.yyyy") LocalDate date, Pageable pageable) {
        return yourService.yourServiceMethod(date, pageable);
    }
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接