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

SpringBoot单向@ManyToOne关联下AccountRequestStatus实体更新失败问题

问题根因

1. 事务配置错误

AccountRequestStatusServiceImpl类上标注了@Transactional(readOnly = true),方法上的@Transactional默认会继承类上的只读属性,导致保存方法实际运行在只读事务中,JPA会忽略所有修改操作的持久化动作,自然不会把更新刷到数据库。

2. 更新逻辑缺失查询步骤

你更新状态时直接新构造了AccountRequestStatus对象,没有先从数据库查询已存在的对应记录,生成的实体主键id为空,JPA的save方法会将其识别为全新的实体尝试插入,而不是更新已有记录。

3. DTO未携带主键信息

更新时构造的AccountRequestStatusDto没有填充已有状态记录的主键id,即使你想做更新,Mapper转换后的实体也没有id值,JPA无法匹配到要更新的数据库行。

修复方案

第一步:调整事务配置+补充查询逻辑

修改AccountRequestStatusServiceImpl的保存方法,显式指定事务为可读写,同时补充先查后更的逻辑:

@Override
@Transactional(readOnly = false)
public void saveAccountRequestStatus(AccountRequestStatusDto accountRequestStatusDto) {
    Long accountRequestId = accountRequestStatusDto.getAccountRequestDto().getId();
    // 先根据关联的账户请求ID查询已存在的状态记录
    Optional<AccountRequestStatus> existStatusOpt = accountRequestStatusRepository.findByAccountRequest_Id(accountRequestId);
    AccountRequestStatus statusToSave;
    if (existStatusOpt.isPresent()) {
        // 已有记录直接更新状态字段即可
        statusToSave = existStatusOpt.get();
        statusToSave.setAccountRequestStatusEnum(accountRequestStatusDto.getAccountRequestStatusEnum());
    } else {
        // 不存在则走新增逻辑
        statusToSave = accountRequestStatusMapper.toAccountRequestStatus(accountRequestStatusDto);
    }
    accountRequestStatusRepository.save(statusToSave);
}

第二步:新增查询接口

在AccountRequestStatusRepository中添加关联查询方法:

Optional<AccountRequestStatus> findByAccountRequest_Id(Long accountRequestId);

第三步:可选适配(如果event中无AccountRequest主键)

如果你从MQ收到的event中没有携带之前保存的AccountRequest主键id,可以先根据AccountRequest的唯一键accountNo和messageId查询到对应的AccountRequest记录,再查对应的状态记录做更新即可。

内容的提问来源于stack exchange,提问作者Faramarz Afzali

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.29 12:24:06