【问题标题】:How to supply LocalDateTime to a jpa/hibernate query?如何将 LocalDateTime 提供给 jpa/hibernate 查询?
【发布时间】:2020-06-04 01:35:45
【问题描述】:

我正在我的@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

【问题讨论】:

    标签: postgresql hibernate spring-boot jpa spring-data-rest


    【解决方案1】:

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

    这篇文章解释了两种选择:https://www.baeldung.com/spring-date-parameters

    【讨论】:

      【解决方案2】:

      @DateTimeFormat 标记它,让 Spring 正确转换它:

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

      【讨论】:

        【解决方案3】:

        选项 1:为所有 Spring Boot App REST Endpoints 全局设置日期/时间格式

        您可以全局配置 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 Endpoint 设置日期/时间格式

        如果您希望单独为每个端点设置格式,则必须使用 @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);
            }
        }
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2015-03-01
          • 1970-01-01
          • 2016-09-12
          • 1970-01-01
          • 2012-03-27
          • 2021-05-26
          相关资源
          最近更新 更多