如何格式化LocalDate并在Spring Boot中按年月查询销售数据
解决方案
你当前的代码只能查询指定某一天的销售记录,要实现按年月查询整月数据,需要分三步调整:
1. 解析前端传入的"July-2024"格式字符串
用DateTimeFormatter解析英文月份+年份的格式,转换成YearMonth对象后,可获取当月的起止日期:
// 指定英文月份解析的Locale,避免中文环境下解析失败 DateTimeFormatter formatter = DateTimeFormatter.ofPattern("MMMM-yyyy", Locale.ENGLISH); String inputMonthYear = "July-2024"; YearMonth yearMonth = YearMonth.parse(inputMonthYear, formatter); // 获取当月第一天和最后一天 LocalDate monthStart = yearMonth.atDay(1); LocalDate monthEnd = yearMonth.atEndOfMonth();
2. 修改SaleRepository,支持整月查询
有两种常用实现方式:
方式一:JPA派生查询(推荐,简洁)
利用Between关键字查询日期范围:
@Repository public interface SaleRepository extends JpaRepository<SaleEntity, Long> { // 查询datePurchased在起止日期之间的所有记录 List<SaleEntity> findByDatePurchasedBetween(LocalDate startDate, LocalDate endDate); // 如果只需要统计销售数量,直接用count方法更高效 Long countByDatePurchasedBetween(LocalDate startDate, LocalDate endDate); }
方式二:JPQL自定义查询(灵活)
直接匹配年份和月份,不用依赖日期范围:
@Repository public interface SaleRepository extends JpaRepository<SaleEntity, Long> { @Query("SELECT s FROM SaleEntity s WHERE YEAR(s.datePurchased) = ?1 AND MONTH(s.datePurchased) = ?2") List<SaleEntity> findByYearAndMonth(int year, int month); // 统计数量的版本 @Query("SELECT COUNT(s) FROM SaleEntity s WHERE YEAR(s.datePurchased) = ?1 AND MONTH(s.datePurchased) = ?2") Long countByYearAndMonth(int year, int month); }
3. 调整服务层方法
根据选择的Repository方式,修改业务逻辑:
对应方式一的服务方法:
private List<SaleEntity> getSelectedMonthSale(String monthYearStr) { DateTimeFormatter formatter = DateTimeFormatter.ofPattern("MMMM-yyyy", Locale.ENGLISH); YearMonth yearMonth = YearMonth.parse(monthYearStr, formatter); LocalDate monthStart = yearMonth.atDay(1); LocalDate monthEnd = yearMonth.atEndOfMonth(); return saleRepository.findByDatePurchasedBetween(monthStart, monthEnd); } // 如果只需要数量,用这个 private Long getSelectedMonthSaleCount(String monthYearStr) { DateTimeFormatter formatter = DateTimeFormatter.ofPattern("MMMM-yyyy", Locale.ENGLISH); YearMonth yearMonth = YearMonth.parse(monthYearStr, formatter); LocalDate monthStart = yearMonth.atDay(1); LocalDate monthEnd = yearMonth.atEndOfMonth(); return saleRepository.countByDatePurchasedBetween(monthStart, monthEnd); }
对应方式二的服务方法:
private List<SaleEntity> getSelectedMonthSale(String monthYearStr) { DateTimeFormatter formatter = DateTimeFormatter.ofPattern("MMMM-yyyy", Locale.ENGLISH); YearMonth yearMonth = YearMonth.parse(monthYearStr, formatter); return saleRepository.findByYearAndMonth(yearMonth.getYear(), yearMonth.getMonthValue()); } // 统计数量的版本 private Long getSelectedMonthSaleCount(String monthYearStr) { DateTimeFormatter formatter = DateTimeFormatter.ofPattern("MMMM-yyyy", Locale.ENGLISH); YearMonth yearMonth = YearMonth.parse(monthYearStr, formatter); return saleRepository.countByYearAndMonth(yearMonth.getYear(), yearMonth.getMonthValue()); }
关键注意点
- 解析英文月份时必须指定
Locale.ENGLISH,否则中文环境下默认Locale无法识别"July"这类英文月份名。 - 如果只需要销售数量,优先使用
count开头的方法,避免加载大量实体数据,提升性能。
内容的提问来源于stack exchange,提问作者Ukeme Elijah
相关产品推荐
相关产品推荐

