You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.13 16:02:37