JPA保存含UserRoles的User实体触发ORA-02291约束错误的解决咨询
保存包含UserRoles集合的User实体时,触发外键约束错误:
oracle.jdbc.OracleDatabaseException: ORA-02291: integrity constraint (APP_OWNER.SYS_C009043) violated - parent key not found
其中SYS_C009043是USER_ROLES表中要求userId必须存在于USER表的外键约束。请问能否让JPA在保存User后自动设置UserRoles的userId再保存?还是必须移除级联保存,先保存User,手动设置UserRoles的userId后再保存角色?
现有实体代码
User 实体
import lombok.*; import javax.persistence.*; import java.sql.Timestamp; import java.util.List; @Entity @Table(name = "USER") @Data @Builder @AllArgsConstructor @NoArgsConstructor @EqualsAndHashCode(callSuper = true) public class User { @Id @GeneratedValue(strategy = GenerationType.AUTO) private long userId; @JoinColumn(name = "userId", referencedColumnName = "userId") @OneToMany(cascade=CascadeType.ALL) private List<UserRoles> userRoles; }
UserRoles 实体
import lombok.*; import javax.persistence.*; @Entity @Table(name = "USER_ROLES") @Data @Builder @AllArgsConstructor @NoArgsConstructor @EqualsAndHashCode(callSuper = true) public class UserRoles { @Id @GeneratedValue(strategy = GenerationType.AUTO) private long userRolesId; @Column private long userId; @Column private long roleId; }
解决方案
不需要手动分步保存,修正JPA的关联映射配置后,就能让JPA自动处理外键赋值:
修正User实体的关联注解
当前@OneToMany配置缺少双向关联映射,且@JoinColumn使用错误。外键字段在USER_ROLES表,应由多的一方维护关联,所以修改@OneToMany配置:@OneToMany(mappedBy = "user", cascade = CascadeType.ALL, orphanRemoval = true) private List<UserRoles> userRoles;修改UserRoles实体,添加双向关联
把原有的userId字段替换为User类型的关联属性,通过@ManyToOne和@JoinColumn指定外键:@ManyToOne(fetch = FetchType.LAZY) @JoinColumn(name = "userId", nullable = false) private User user; // 移除原来的userId字段 // @Column // private long userId;建立对象间的双向关联
创建User和UserRoles实例时,需要互相绑定关联关系:User user = new User(); UserRoles role = new UserRoles(); role.setRoleId(1L); role.setUser(user); // 绑定关联的User对象 user.setUserRoles(List.of(role)); userRepository.save(user);
完成以上配置后,JPA会自动按顺序执行:先插入User记录生成userId,再将该userId赋值给UserRoles的外键字段,最后插入UserRoles记录,全程无需手动设置userId。
如果坚持保留userId字段而不用对象关联(不推荐,不符合JPA最佳实践),可以在User实体的@OneToMany中添加@MapKeyColumn(name = "userId"),但这种方式需要手动维护关联,远不如对象关联便捷。
内容的提问来源于stack exchange,提问作者lateve8692

