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

JPA OneToOne映射保存实体报行被其他事务更新/删除错误

问题根因

这个异常是JPA双向关联配置和持久化逻辑不匹配导致的,核心触发点有三个:

  • 双向1对1关联的级联逻辑和手动保存冲突:InvitationLink作为外键持有端(配置了@JoinColumn)设置了CascadeType.ALL,调用invitationLinkRepository.save()时会自动级联保存关联的瞬态Team对象,后续手动调用teamRepository.save(team)属于重复持久化同一个实体,JPA持久化上下文检测到实体状态和数据库预期不一致,就会抛出该异常。
  • Lombok@Data注解自动生成的toString、equals、hashCode方法会遍历关联字段,双向关联下会出现无限递归调用,也就是你之前碰到的递归报错。
  • 若UUID主键生成策略未明确指定,JPA可能无法正确判断实体是否为未保存状态,触发unsaved-value映射错误。
修复方案

按以下步骤调整即可解决问题:

  1. 处理双向关联的递归问题:给两个实体的双向关联字段添加Lombok排除注解,避免生成方法时循环调用。
  2. 简化持久化逻辑:删除重复的teamRepository.save(team)调用,级联配置会自动完成关联Team对象的持久化,不需要手动重复保存。
  3. (可选,若仍报unsaved-value错误)明确指定UUID主键的生成策略,避免JPA状态判断错误。
修正后代码

Team实体

@Table(name = "team")
@Entity
@AllArgsConstructor
@NoArgsConstructor
@Data
@With
public class Team {

    @Id
    @Column
    @GeneratedValue
    private UUID id;

    @Column
    private String teamName;

    @OneToMany(cascade = CascadeType.ALL)
    private List<TeamMember> teamMembers;

    // 排除双向关联字段,避免递归
    @ToString.Exclude
    @EqualsAndHashCode.Exclude
    @OneToOne(mappedBy = "team")
    private InvitationLink invitationLink;
}

InvitationLink实体

@Entity
@Data
@With
@NoArgsConstructor
@AllArgsConstructor
@Table(name = "invitationLink")
public class InvitationLink {
    @Id
    @Column
    @GeneratedValue
    private UUID id;

    // 排除双向关联字段,避免递归
    @ToString.Exclude
    @EqualsAndHashCode.Exclude
    @OneToOne(cascade = CascadeType.ALL)
    @JoinColumn(name = "team_id", referencedColumnName = "id")
    private Team team;

    @Column
    private String invitationNumbers;
}

业务保存逻辑

@Override
@Transactional
public void createTeam(UserDto userDto, TeamDto teamDto) throws JSONException {
    // 此处省略无关业务代码    
    InvitationLink invitationLink = new InvitationLink();
    invitationLink.setInvitationNumbers(StringUtils.generateShortUUID());
    // 正确设置双向关联
    invitationLink.setTeam(team);
    team.setInvitationLink(invitationLink);
    
    // 外键持有端单次保存即可,级联自动持久化关联的Team
    invitationLinkRepository.save(invitationLink);
    
    // 非级联管理的实体正常单独保存
    userRepository.save(user);
    // 如果teamMember已经加入team的teamMembers列表,这行可以省略,OneToMany的级联会自动保存
    teamMemberRepository.save(teamMember);
}

注意:如果调整后仍触发unsaved-value相关报错,给两个实体的主键字段替换UUID生成策略即可:

@Id
@Column
@GeneratedValue(generator = "uuid2")
@GenericGenerator(name = "uuid2", strategy = "uuid2")
private UUID id;

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.28 05:15:43