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

Spring Data JPA关联映射引发插入重复列的问题解决

解决Spring Data JPA插入DB2时重复列导致的SQL错误121

问题原因

你的User实体同时维护了userId、regCode实体字段,以及用于关联UserType的同名@JoinColumn映射。JPA在生成INSERT语句时,会同时把实体字段和关联映射的列纳入插入字段列表,导致重复列冲突(DB2错误121)。

最优解决方案

通过调整关联映射的insertable和updatable属性,让JPA仅用关联映射做查询加载,插入/更新操作由实体自身字段维护,同时配置级联保存实现User和UserType的批量插入。

1. 修改User实体的关联映射

User.java调整:

@Data
@AllArgsConstructor
@NoArgsConstructor
@Entity
@Table
public class User implements Serializable {

    @Id
    private Long userId;
    private String name;
    private String address;
    private String regCode;
    private String subjectCode;

    // 调整UserType关联:设置级联保存,关联列仅用于查询
    @OneToOne(fetch = FetchType.LAZY, cascade = {CascadeType.PERSIST, CascadeType.MERGE})
    @JoinColumns({
        @JoinColumn(name = "userId", referencedColumnName = "userId", insertable = false, updatable = false),
        @JoinColumn(name = "regCode", referencedColumnName = "regCode", insertable = false, updatable = false)
    })
    private UserType userType;

    // 调整RegData关联:关联列仅用于查询
    @ManyToOne(fetch = FetchType.LAZY)
    @JoinColumnsOrFormulas(value = {
            @JoinColumnOrFormula(formula = @JoinFormula(value = "regCode", referencedColumnName = "regCode", insertable = false, updatable = false)),
            @JoinColumnOrFormula(column = @JoinColumn(name = "subjectCode", referencedColumnName = "subjectCode", insertable = false, updatable = false))
    })
    private RegData regData;
}
  • insertable = false, updatable = false:告诉JPA这些关联列不由映射关系维护,仅用于查询时的关联加载,避免插入/更新时重复生成字段。
  • cascade = {CascadeType.PERSIST, CascadeType.MERGE}:配置级联保存/更新,保存User时自动同步保存关联的UserType。

2. 完善插入代码的UserType主键设置

UserType的联合主键需要userId和regCode两个字段,之前的代码仅设置了userId,需要补充regCode:

// 手动分配下一个ID值
Long nextId = ...;
User user = new User();
user.setUserId(nextId);
user.setName("测试用户");
user.setAddress("测试地址");
user.setRegCode("REG001"); // 设置User的regCode
user.setSubjectCode("SUB001");

// 创建并关联UserType
UserType type = new UserType();
UserTypeId id = new UserTypeId();
id.setUserId(nextId);
id.setRegCode(user.getRegCode()); // 补充设置regCode,完善联合主键
type.setId(id);
type.setTypeCode(1); // 设置typeCode值
user.setUserType(type);

// 设置从数据库获取的RegData
user.setRegData(regDataRepository.findById(new RegDataId("REG001", "SUB001")).orElse(null));

// 保存User,级联保存UserType
userRepository.save(user);

3. 验证效果

修改后JPA生成的INSERT语句将不再包含重复列,示例如下:

insert into USER (USERID, NAME, ADDRESS, REG_CODE, SUBJECT_CODE) values (?, ?, ?, ?, ?)

同时会自动生成UserType的INSERT语句:

insert into USER_TYPE (USERID, REG_CODE, TYPE_CODE) values (?, ?, ?)

查询时依然可以通过user.getUserType()和user.getRegData()正常加载关联数据,无需手动查询赋值。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.11 21:25:18