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
相关产品推荐
相关产品推荐

