【发布时间】: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 数据足够智能,可以通过方法名称制定查询。我认为问题在于您使用>进行比较的方式。因此,将这些复杂性留给框架。不用@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