Spring Boot执行MySQL删除48小时前数据的SQL查询报错问题
解决Spring Boot中删除48小时前数据的JPQL解析错误问题
问题原因
你遇到的错误是因为JPA默认把@Query里的语句当作JPQL(Java Persistence Query Language)解析,而JPQL不支持MySQL原生的INTERVAL 48 HOUR语法,所以解析器会抛出语法错误。
解决方法
方法一:使用原生MySQL查询(推荐)
直接让JPA执行原生SQL语句,只需在@Query注解里添加nativeQuery = true参数,同时别忘了加上@Modifying注解(因为这属于DML修改操作):
import org.springframework.data.jpa.repository.Modifying; import org.springframework.data.jpa.repository.Query; import org.springframework.data.repository.CrudRepository; import org.springframework.transaction.annotation.Transactional; public interface ScheduleRepository extends CrudRepository<Schedule, Long> { @Modifying @Transactional // 部分场景下需要显式开启事务 @Query(value = "DELETE FROM schedule WHERE date_time < NOW() - INTERVAL 48 HOUR", nativeQuery = true) void deleteOldSchedules(); }
这种方式会把语句直接传给MySQL执行,和你在数据库客户端运行的效果完全一致,不会有语法解析问题。
方法二:使用JPQL兼容的日期计算
如果不想用原生SQL,可以用JPQL的语法实现相同逻辑,比如调用MySQL的DATE_SUB函数,或者使用JPQL自带的日期操作:
@Modifying @Transactional @Query("DELETE FROM Schedule s WHERE s.dateTime < FUNCTION('DATE_SUB', CURRENT_TIMESTAMP, FUNCTION('INTERVAL', 48, 'HOUR'))") void deleteOldSchedules();
部分JPA实现(比如Hibernate)支持更简洁的写法:
@Modifying @Transactional @Query("DELETE FROM Schedule s WHERE s.dateTime < CURRENT_TIMESTAMP - INTERVAL '48' HOUR") void deleteOldSchedules();
不过这种写法依赖具体的JPA实现,兼容性不如原生SQL稳定。
注意事项
- 执行DELETE、UPDATE这类修改操作时,必须添加
@Modifying注解,否则JPA会误认为是查询操作而报错。 - 部分Spring Boot配置下,需要显式添加
@Transactional注解开启事务,否则可能无法执行修改操作。
内容的提问来源于stack exchange,提问作者hilmi uğur
相关产品推荐
相关产品推荐

