Spring JPA执行Update查询报错‘expecting SELECT query’求助
问题解决:Hibernate UPDATE语句触发IllegalSelectQueryException报错
问题代码
仓库接口中的更新方法实现:
@Modifying @Lock(LockModeType.PESSIMISTIC_FORCE_INCREMENT) @Query("UPDATE TradeTransaction tt set tt.externalStatus = :status where tt.id = :id") int updateTransactionExternalStatus(@Param("status") TradeTransaction.ExternalStatus status, @Param("id") Long id);
报错信息
org.hibernate.query.IllegalSelectQueryException: Expecting a SELECT Query [org.hibernate.query.sqm.tree.select.SqmSelectStatement], but found org.hibernate.query.sqm.tree.update.SqmUpdateStatement [UPDATE TradeTransaction tt set tt.externalStatus = :status where tt.id = :id]
原因分析与解决方案
问题核心在于**@Lock注解仅支持SELECT查询**,无法与UPDATE这类DML修改语句搭配使用。尽管@Modifying注解用于标记非SELECT的修改操作,但@Lock的存在会让Hibernate默认判定这是一条查询语句,最终触发语句类型不匹配的错误。
方案1:保留锁机制的正确写法
如果确实需要悲观锁+更新的业务逻辑,应先通过带@Lock的SELECT语句获取实体,修改属性后由ORM自动同步更新:
@Lock(LockModeType.PESSIMISTIC_FORCE_INCREMENT) @Query("SELECT tt FROM TradeTransaction tt WHERE tt.id = :id") Optional<TradeTransaction> findByIdForUpdate(@Param("id") Long id); // 业务层调用示例 tradeTransactionRepository.findByIdForUpdate(id).ifPresent(tt -> { tt.setExternalStatus(status); // 无需手动调用save,事务提交时ORM会自动执行更新 });
方案2:移除锁机制快速解决
如果不需要事务控制和锁逻辑,直接删除@Lock注解即可消除报错:
@Modifying @Query("UPDATE TradeTransaction tt set tt.externalStatus = :status where tt.id = :id") int updateTransactionExternalStatus(@Param("status") TradeTransaction.ExternalStatus status, @Param("id") Long id);
内容的提问来源于stack exchange,提问作者nasch
相关产品推荐
相关产品推荐

