在 SpringDataMongoDB 上使用 JSON 在 MongoDB 上进行日期查询

Making Date queries on MongoDB using JSON on SpringDataMongoDB

我在使用 JHipster.[=24 创建的项目的 SpringDataMongoDB 上使用 @Query 注释进行 MongoDB Date 查询时遇到一些问题=]

自从使用 JHipster 创建项目以来,大多数查询都是使用 Spring Data query builder mechanism and for more refined queries, instead of using Type-safe Query methods I decided to stick with JHipster's standard configuration and make personalized queries using @Query annotation that allows the creation of MongoDBJSON 查询创建的。

但是,我无法在我的 Json 查询中引用 DateLocalDate.

类型的任何实体字段

我尝试采用 的答案作为解决方案,但没有成功。

查询尝试

@Repository
public interface CourseClassRepository extends MongoRepository<CourseClass, String> {

    // WORKS - query with `endDate` directly constructed by Spring Data
    // This sollution however isn't enought, since 'experience_enrollments.device_id' cannot be used as a parameter
    List<CourseClass> findAllByInstitutionIdAndEndDateIsGreaterThanEqual(Long institutionId, LocalDate dateLimit);

    // Using @Query to create a JSON query doesn't work.
    // apparently data parameter cannot be found. This is weird, considering that in any other @Query created the parameter is found just fine.
    // ERROR: org.bson.json.JsonParseException: Invalid JSON input. Position: 124. Character: '?'
    @Query(" { 'experience_enrollments.device_id' : ?0, 'institution_id': ?1, 'end_date': { $gte: { $date: ?2 } } } ")
    List<CourseClass> findAllByExperienceDeviceAndInstitutionIdAndEndDate(String deviceId, Long institutionId, Date dateLimit);

    // Adopting the Whosebug answer mentioned above also throws an error. I belive that this error is related to the fact that '?2' is being interpreted as a String value and not as reference to a parameter
    // ERROR: org.bson.json.JsonParseException: Failed to parse string as a date
    @Query(" { 'experience_enrollments.device_id' : ?0, 'institution_id': ?1, 'end_date': { $gte: { $date: '?2' } } } ")
    List<CourseClass> findAllByExperienceDeviceAndInstitutionIdAndEndDate(String deviceId, Long institutionId, Date dateLimit);

    // Even hardcoding the date parameter, the query throws an error
    // ERROR: org.bson.codecs.configuration.CodecConfigurationException: Can't find a codec for class java.time.ZonedDateTime.
    @Query(" { 'experience_enrollments.device_id' : ?0, 'institution_id': ?1, 'end_date': { '$gte': { '$date': '2015-05-16T07:55:23.257Z' } } }")
    List<CourseClass> findAllByExperienceDeviceAndInstitutionIdAndEndDate(String deviceId, Long institutionId);
}

数据库配置

@Configuration
@EnableMongoRepositories("br.com.pixinside.lms.course.repository")
@Profile("!" + JHipsterConstants.SPRING_PROFILE_CLOUD)
@Import(value = MongoAutoConfiguration.class)
@EnableMongoAuditing(auditorAwareRef = "springSecurityAuditorAware")
public class DatabaseConfiguration {
     @Bean
        public MongoCustomConversions customConversions() {
            List<Converter<?, ?>> converters = new ArrayList<>();
            converters.add(DateToZonedDateTimeConverter.INSTANCE);
            converters.add(ZonedDateTimeToDateConverter.INSTANCE);
            return new MongoCustomConversions(converters);
        }
}

日期转换器

    public static class DateToZonedDateTimeConverter implements Converter<Date, ZonedDateTime> {

        public static final DateToZonedDateTimeConverter INSTANCE = new DateToZonedDateTimeConverter();

        private DateToZonedDateTimeConverter() {
        }

        @Override
        public ZonedDateTime convert(Date source) {
            return source == null ? null : ZonedDateTime.ofInstant(source.toInstant(), ZoneId.systemDefault());
        }
    }

    public static class ZonedDateTimeToDateConverter implements Converter<ZonedDateTime, Date> {

        public static final ZonedDateTimeToDateConverter INSTANCE = new ZonedDateTimeToDateConverter();

        private ZonedDateTimeToDateConverter() {
        }

        @Override
        public Date convert(ZonedDateTime source) {
            return source == null ? null : Date.from(source.toInstant());
        }
    }

结果如Christoph Strobl, the behavior was, in fact, a bug所述。因此,在 Spring Data MongoDB 的未来版本中,无需担心这一点。到此为止,我将分享我的解决方案。

由于我无法使用 MongoDBJSon 创建查询,所以我使用了 MongoTemplate,一切正常。

import org.springframework.data.mongodb.core.MongoTemplate;
import static org.springframework.data.mongodb.core.query.Criteria.where;
import static org.springframework.data.mongodb.core.query.Query.query;   

    @Autowired
    public MongoTemplate mongoTemplate;

    public List<CourseClass> findEnrolledOnExperienceDeviceWithMaxEndDateAndInstitutionId(String deviceId, LocalDate endDate, Long institutionId) {
        return mongoTemplate.find(query(
            where("experience_enrollments.device_id").is(deviceId)
                .and("institution_id").is(institutionId)
                .and("end_date").gte(endDate)), CourseClass.class);
    }