【问题标题】:spring-boot / spring-data-jpa custom query filtering by Date field returning results without filteringspring-boot / spring-data-jpa 自定义查询过滤由日期字段返回结果而不过滤
【发布时间】:2017-05-18 13:05:35
【问题描述】:

我正在使用 spring-boot-starter-data-jpa-1.5.2.RELEASE 开发一个 spring-boot REST 服务器。我有以下 POJO 类层次结构。首先是基类Entity:

@javax.persistence.Entity
@Inheritance(strategy = InheritanceType.TABLE_PER_CLASS)
public abstract class Entity implements Serializable {    

    @Id
    @Column(name = "id", nullable = false, length = 48)
    public String id = UNINITIALIZED_ID;

    /**
     * The timestamp for when this entity was last updated.
     */
    @Column(columnDefinition = "timestamp with time zone")
    @Temporal(TemporalType.TIMESTAMP)
    public Date updateTimestamp = new Date();

}

接下来是具体的子类 Patient:

@javax.persistence.Entity
@Table(indexes={@Index(columnList="updateTimestamp")})
public class Patient extends Entity {
...
}

我使用自定义方法将我的 PatientRepository 接口定义如下,以获取 updateTimestamp 在指定时间戳之后的患者:

@RepositoryRestResource(collectionResourceRel = "patients", path = "patients")
public interface PatientRepository extends JpaRepository<Patient, String> {
    List<Patient> findByUpdateTimestampAfter(@DateTimeFormat(iso=DateTimeFormat.ISO.DATE_TIME)@Param("after")Date after);
}

由于某些未知原因,当我通过 Advanced Rest Client Chrome 插件发出以下 GET 请求时,updateTimestamnp 的过滤器无法正常工作:

// url example. DateFormat matches @DateTimeFormat on param in query method. 
GET http://127.0.0.1:8090/patients?after=2030-01-10T00:00:00.000-05:00

我希望只返回那些在指定时间戳之后具有 updateTimestamp 的实体,但我得到的是资源集合中的所有实体。

我在 spring-boot 上打开了 DEBUG 日志记录。这是我不确定的问题:

2017-05-18 10:15:56.127 DEBUG 5292 --- [           main] o.s.d.j.r.query.JpaQueryFactory          : Looking up query for method findByUpdateTimestampAfter
2017-05-18 10:15:56.132 DEBUG 5292 --- [           main] o.s.d.jpa.repository.query.NamedQuery    : Looking up named query Patient.findByUpdateTimestampAfter
2017-05-18 10:15:56.133 DEBUG 5292 --- [           main] o.s.d.jpa.repository.query.NamedQuery    : Did not find named query Patient.findByUpdateTimestampAfter

根据@pvpkiran 的良好建议,我编写了以下 Spock 集成测试,并表明在获取 Date 解析后,PatientRepository.findByUpdateTimestampAfter 方法按预期工作:

    @SpringBootTest(classes = com.altran.medmap.server.Application.class, webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
    @Transactional

class PatientRepositorySpec extends Specification {


    @Autowired
    PatientRepository patientRepository;


    @Bean
    @Unroll    
    def 'Should GET #size patients whose updateTimestamp is after: #after'( {
        given:
            DateFormat dateFormat = new SimpleDateFormat('MMM d, yyyy h:mm:ss a');
            Date afterx = dateFormat.parse(after);
        when:
            List<Patient> result = patientRepository.findByUpdateTimestampAfter(after);
        then:
          result.size() == size;
        where: 'result size matches expected'
            after                        | size
            'Jan 1, 2016 00:00:00 AM'    | 2
            'Jan 1, 2030 00:00:00 AM'    | 0

    }            
}

REST API 仍然返回所有实体的事实仍然是一个未解之谜。并不是说我在 Repository 接口中的查询方法参数上指定了 @DateTimeFormat(iso=DateTimeFormat.ISO.DATE_TIME) 并在 rest URL 中使用相同的格式。有什么建议可以从这里去吗?

【问题讨论】:

  • 当您说不工作时,这是否意味着未获取任何记录或者您是否遇到任何异常。您在 DB 中有符合此条件的记录吗?
  • 很抱歉。刚刚更新我正在获取所有实体,而不是在指定时间戳之后具有 updateTimestamp 的子集。
  • 删除您的@Query 并尝试。 Spring 数据足够智能,可以通过方法名称制定查询。我认为问题在于您使用&gt; 进行比较的方式。因此,将这些复杂性留给框架。不用@Query 试试看
  • 感谢@pvpkiran。这给了我返回所有实体而不是子集的相同结果。我在日志中看到以下内容:2017-05-18 09:25:22.580 DEBUG 14192 --- [main] o.s.d.j.r.query.JpaQueryFactory:查找方法 findByUpdateTimestampAfter 的查询 2017-05-18 09:25:22.585 DEBUG 14192 -- - [main] os.d.jpa.repository.query.NamedQuery:查找命名查询 Patient.findByUpdateTimestampAfter 2017-05-18 09:25:22.586 DEBUG 14192 --- [main] o.s.d.jpa.repository.query.NamedQuery:未找到命名查询 Patient.findByUpdateTimestampAfter
  • 公开日期 updateTimestamp = new Date();为什么要在这里初始化日期对象?

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


【解决方案1】:

我终于找出了导致其余界面不提供过滤结果的愚蠢错误。我的 URL 路径不正确。

//Incorrect URL
http://127.0.0.1:8090/patients?after=2030-01-10T00:00:00.000-05:00

//Correct URL based on spring-data-rest default conventions
http://127.0.0.1:8090/patients/search/findByUpdateTimestampAfter?after=2030-01-10T00:00:00.000-05:00

请注意,在修复 URL 后,我收到了日期解析错误。我为 here 创建了一个新问题。

感谢@pvpkiran 和@Afridi 的热心帮助。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2020-01-25
    • 2019-10-31
    • 2017-08-29
    • 2018-08-29
    • 2021-12-03
    • 1970-01-01
    • 2019-10-12
    相关资源
    最近更新 更多