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

