Spring中如何通过日期匹配Timestamp列实现数据查询?
问题描述
我通过以下代码获取了一个格式为2024-09-10 00:00:00.0的Date对象myCurrentDate:
Date myCurrentDate = calendarRepository.getMyCurrentDate();
数据库的product_table表中有一个timestamp类型的create_date列,数据示例如下:
| product_name | create_date |
|---|---|
| Sugar | 2024-09-10 11:37:25 |
| Chips | 2024-09-08 12:20:52 |
| Coffee | 2024-09-10 15:12:33 |
| Oranges | 2024-09-10 20:52:15 |
我需要查询当天创建的所有产品(即Sugar、Coffee、Oranges),但当前使用的查询代码返回空结果:
List<Products> productsReults= productRepository.findByCrtDt(myCurrentDate);
对应的JPA Repository定义:
List<Products> findByCrtDt(Date myCurrentDate);
原因是myCurrentDate的时分秒为00:00:00.0,和数据库中带具体时分秒的时间戳不匹配。要求不能修改数据库列类型(从Timestamp改为Date),请问如何修改查询逻辑?
解决方案
方法1:按当天时间范围查询
计算出myCurrentDate当天的起始时间(00:00:00)和次日起始时间(次日00:00:00),用Between匹配落在该区间内的数据:
首先在Repository中定义方法:
List<Products> findByCreateDateBetween(Date startDate, Date endDate);
然后在业务代码中生成时间范围:
// 当天起始时间就是myCurrentDate本身 Date startOfDay = myCurrentDate; // 计算次日00:00:00 Calendar calendar = Calendar.getInstance(); calendar.setTime(myCurrentDate); calendar.add(Calendar.DAY_OF_MONTH, 1); calendar.set(Calendar.HOUR_OF_DAY, 0); calendar.set(Calendar.MINUTE, 0); calendar.set(Calendar.SECOND, 0); calendar.set(Calendar.MILLISECOND, 0); Date endOfDay = calendar.getTime(); // 执行查询 List<Products> productsResults = productRepository.findByCreateDateBetween(startOfDay, endOfDay);
方法2:用数据库日期函数忽略时分秒
通过JPA调用数据库的日期处理函数,提取日期部分进行匹配,Repository方法定义如下:
@Query("SELECT p FROM Products p WHERE FUNCTION('DATE', p.createDate) = FUNCTION('DATE', :currentDate)") List<Products> findByCreateDateDatePart(@Param("currentDate") Date currentDate);
注意:不同数据库的日期函数名称有差异:
- MySQL/MariaDB:使用
DATE()函数,上述写法直接可用 - PostgreSQL:可替换为
DATE_TRUNC('day', p.createDate) = DATE_TRUNC('day', :currentDate) - Oracle:替换为
TRUNC(p.createDate) = TRUNC(:currentDate)
方法3:结合Java 8时间API简化查询
如果实体类允许调整字段类型(不修改数据库列),将createDate改为LocalDateTime:
@Column(name = "create_date", columnDefinition = "TIMESTAMP") private LocalDateTime createDate;
然后在Repository中定义基于时间范围的衍生方法:
List<Products> findByCreateDateBetween(LocalDateTime startOfDay, LocalDateTime endOfDay);
业务代码中转换时间:
LocalDate currentLocalDate = myCurrentDate.toInstant().atZone(ZoneId.systemDefault()).toLocalDate(); LocalDateTime startOfDay = currentLocalDate.atStartOfDay(); LocalDateTime endOfDay = currentLocalDate.plusDays(1).atStartOfDay(); List<Products> productsResults = productRepository.findByCreateDateBetween(startOfDay, endOfDay);
内容的提问来源于stack exchange,提问作者craftdeer
相关产品推荐
相关产品推荐

