Spring Data JPA:日期减2天的更新查询无法正常工作
修复你的HotelDailyPrice更新语句问题
嘿,我来帮你排查下这条JPQL更新语句为啥跑不起来,这里面有几个容易踩的坑:
- 参数绑定完全错了:你第一个参数传的是
Hotel对象,但子查询里写hp.id = ?1,这相当于把整个Hotel实例和hp.id做对比,数据库肯定懵了!得改成绑定酒店的ID,比如hp.hotel.id = ?1(假设HotelPrice里关联Hotel的字段叫hotel),或者干脆直接传Long hotelId当参数,更直接。 - 子查询可能返回Null:要是没找到两天内的
HotelPrice记录,avg(hp.price)会返回Null,这会把hdp.price设成Null,大概率不是你想要的。建议用COALESCE函数给个默认值,比如默认0,避免空值问题。 - 日期计算不兼容JPQL标准:
CURRENT_DATE - 2这种写法不是JPQL的标准语法,不同JPA实现(比如Hibernate)和数据库(MySQL/PostgreSQL)的支持不一样。得用标准的函数来处理日期偏移,比如MySQL用FUNCTION('DATE_SUB', CURRENT_DATE, 2),PostgreSQL可以直接写CURRENT_DATE - INTERVAL '2 days'(要是用原生查询的话记得加nativeQuery = true)。 - 没加WHERE条件会炸锅:原语句没有WHERE子句,执行起来会更新所有
HotelDailyPrice记录!这绝对是大问题,必须加上条件限定只更新目标酒店的记录。 - 类型与可读性问题:用
?1、?2这种位置参数不如命名参数直观,而且dayDate用String类型很容易出格式错误,换成LocalDate才是类型安全的正确姿势。
给你改好的代码示例,我用了命名参数、处理了空值、加了WHERE条件,还调整了类型:
@Transactional @Modifying @Query("UPDATE HotelDailyPrice hdp " + "SET hdp.price = COALESCE((SELECT AVG(hp.price) " + " FROM HotelPrice hp " + " WHERE hp.hotel.id = :hotelId " + " AND hp.updateDate > FUNCTION('DATE_SUB', CURRENT_DATE, 2)), 0), " + " hdp.day = :dayDate " + "WHERE hdp.hotel.id = :hotelId") int updateDailyAveragePrice(@Param("hotelId") Long hotelId, @Param("dayDate") LocalDate dayDate);
要是你还是想保留Hotel作为参数,也可以这么写:
@Transactional @Modifying @Query("UPDATE HotelDailyPrice hdp " + "SET hdp.price = COALESCE((SELECT AVG(hp.price) " + " FROM HotelPrice hp " + " WHERE hp.hotel = :hotel " + " AND hp.updateDate > FUNCTION('DATE_SUB', CURRENT_DATE, 2)), 0), " + " hdp.day = :dayDate " + "WHERE hdp.hotel = :hotel") int updateDailyAveragePrice(@Param("hotel") Hotel hotel, @Param("dayDate") LocalDate dayDate);
另外,把返回值改成int能拿到更新的行数,方便你确认有没有命中目标记录,比void实用多了~
内容的提问来源于stack exchange,提问作者Ramon De Les Olives
相关产品推荐
相关产品推荐

