Spring Boot JPA自定义更新方法启动报No property found错误
问题根因
报错核心为Spring Data JPA未识别到setConversationInfoById方法上声明的自定义@Query,转而按方法名派生查询规则,解析方法名时将setConversationInfoById识别为实体属性访问路径,因Conversation实体不存在对应属性抛出异常。
触发问题的两个直接原因:
- 返回值类型不符合
@Modifying操作规范:标记@Modifying的UPDATE/DELETE类操作,默认返回值为受影响的数据行数,对应类型为Int(Java环境为Integer/void),原代码声明返回List<Conversation>属于非法返回值,导致JPA初始化Repository时无法匹配自定义查询逻辑。 - 修改操作缺失事务边界:所有涉及数据修改的JPA操作必须运行在事务上下文中,未添加
@Transactional注解时JPA不会将该方法识别为合法的修改操作。
额外注意原业务逻辑存在bug:Service层更新时传入的是查询得到的原有friend字段值,执行更新后数据不会发生任何变化,不符合切换好友标识的需求。
修复方案
按以下步骤调整代码即可解决:
- 修正Repository层方法返回值,将
List<Conversation>替换为Int(接收受影响行数)或Unit(无返回值) - 为修改操作添加事务注解,可选择在Repository方法上添加,或统一在Service层业务方法上添加(推荐后者,便于统一管控事务边界)
- 修正Service层更新逻辑,传入取反后的好友标识,实现状态切换
修复后的Repository代码参考:
@Modifying @Query("UPDATE Conversation conversation SET conversation.friend = ?1 WHERE conversation.id = ?2") // 如果Service层加了@Transactional,这里不需要重复添加 fun setConversationInfoById(friend: Boolean, id: UUID): Int
修复后的Service代码参考:
@Transactional // 事务边界加在业务方法上 fun addDeleteFriend(conversation: Conversation) { val openedConversation = db.findByIdOrNull(conversation.id) if (openedConversation == null) { db.save(conversation) } else { // 对原有状态取反,实现添加/删除好友的切换效果 db.setConversationInfoById(!openedConversation.friend, openedConversation.id) } }
Controller层代码无需调整,重启服务即可正常运行。
内容的提问来源于stack exchange,提问作者Krystian Szozda
相关产品推荐
相关产品推荐

