Spring Data Rest关联查询:用户关联费用的日期范围查询方法
嘿,我明白你的困扰了——你想基于单个用户的上下文,调用日期范围查询来筛选他的费用,但试了半天URL都没生效对吧?别慌,Spring Data Rest其实有好几种方式能搞定这个需求,我给你拆解几个最实用的方案:
方案一:在ExpenseRepository里新增带用户维度的查询方法
这个方案是在全局费用查询的基础上,加上用户筛选条件,适合需要同时支持全局和单用户查询的场景。
- 先确认你的Expense实体已经关联了User(应该已经有了,不然你能拿到用户的费用列表):
@Entity public class Expense { // 其他字段... @ManyToOne private User user; private LocalDate date; // Getters & Setters }
- 在ExpenseRepository里新增一个带用户参数的日期范围查询方法,记得用
@Param标注参数,方便URL传递:
@RepositoryRestResource(collectionResourceRel = "expenses", path = "expenses") public interface ExpenseRepository extends JpaRepository<Expense, Long> { // 你已有的全局日期范围查询 List<Expense> findByDateBetween(@Param("startDate") LocalDate startDate, @Param("endDate") LocalDate endDate); // 新增:按用户ID+日期范围查询(比传User对象更直观) List<Expense> findByUserIdAndDateBetween( @Param("userId") Long userId, @Param("startDate") LocalDate startDate, @Param("endDate") LocalDate endDate ); }
- 现在你就可以用这个URL调用了:
http://localhost:8080/api/expenses/search/findByUserIdAndDateBetween?userId=1&startDate=2018-02-01&endDate=2018-02-28
小贴士:如果想用用户的资源URI作为参数(比如
user=http://localhost:8080/api/users/1),可以把方法参数改成User user,Spring Data Rest会自动解析URI对应的实体。
方案二:在UserRepository里定义关联查询(更贴合单用户上下文)
这个方案把查询挂在用户资源的搜索端点下,逻辑上更符合“从单个用户出发查费用”的场景。
- 先确认User实体里有Expense的关联集合:
@Entity public class User { // 其他字段... @OneToMany(mappedBy = "user") private List<Expense> expenses; // Getters & Setters }
- 在UserRepository里新增查询方法,方法名要遵循Spring Data的命名规则(
find[关联字段名]By[条件]),还可以用@RestResource自定义端点路径:
@RepositoryRestResource(collectionResourceRel = "users", path = "users") public interface UserRepository extends JpaRepository<User, Long> { // 自定义搜索路径,让URL更友好 @RestResource(path = "expenses-by-date-range") List<Expense> findExpensesByDateBetween( @Param("startDate") LocalDate startDate, @Param("endDate") LocalDate endDate ); }
- 调用的URL就变成了用户资源下的搜索端点:
http://localhost:8080/api/users/1/search/expenses-by-date-range?startDate=2018-02-01&endDate=2018-02-28
方案三:用动态查询参数(无需新增方法)
如果你不想加新的Repository方法,Spring Data Rest支持直接在子资源URL后面加过滤参数,前提是你的date字段有对应的getter。
直接用这个URL就行:http://localhost:8080/api/users/1/expense?date.greaterThanOrEqual=2018-02-01&date.lessThanOrEqual=2018-02-28
注意:Spring Data Rest默认支持ISO日期格式(yyyy-MM-dd),你原来用的
dd-MM-yyyy会报错。如果想保留这个格式,需要添加一个日期转换器配置:
@Configuration public class RestConfig implements RepositoryRestConfigurer { @Override public void configureConversionService(ConfigurableConversionService conversionService) { conversionService.addConverter(String.class, LocalDate.class, source -> LocalDate.parse(source, DateTimeFormatter.ofPattern("dd-MM-yyyy"))); } }
最后给你个小建议:可以访问http://localhost:8080/api查看所有暴露的端点,确认你的新查询方法是否已经被正确注册,这样能快速排查问题~
内容的提问来源于stack exchange,提问作者Sesha

