首页 > 解决方案 > OneToOne 映射:违反参照完整性约束

问题描述

我正在使用 Spring Data JPA 开发 REST API,需要一些帮助。

我的 REST API 将处理创建组的请求,并根据请求数据将成员分配给组。请求的 URL 将是@PostMapping("/createGroup/{user-id}/groups")

我有以下课程,会员课程:

public class Member {

    private int memberId;

    private String memberName;

    private String memberCity;
// getters / setters

我的请求正文类:

public class AppRequest {

    private String name;

    private String description;

    private List<Member> members;
// getters / setters

我的集团实体:

@Entity
@Table(name="Groups")
public class GroupEntity {

    @Id
    @GeneratedValue(strategy=GenerationType.IDENTITY)
    private int id;

    @OneToOne
    @JoinColumn(name="groupOwnerId")
    private MemberEntity groupOwnerId;

    private String groupName;

    private String description;

    @ManyToMany(cascade=CascadeType.ALL)
    @JoinTable(
            name="Group_Members",
            joinColumns= @JoinColumn(name="id"),
            inverseJoinColumns= @JoinColumn(name="memberId")            
    )
    Set<MemberEntity> members = new HashSet<>();

// getters / setters

我的会员实体:

@Entity
@Table(name="Members")
public class MemberEntity {

    @Id
    @GeneratedValue(strategy=GenerationType.IDENTITY)
    private int memberId;

    private String memberName;

    private String memberCity;

    @ManyToMany(cascade=CascadeType.ALL, mappedBy="members")
    Set<GroupEntity> groups = new HashSet<>();

// getters / setters

最后是我的控制器,

@RestController
public class AppController {

    @Autowired
    MemberRepository memRepo;

    @Autowired
    GroupRepository groupRepo;

@PostMapping("/createGroup/{user-id}/groups")
@Transactional
public ResponseEntity<AppResponse> createGroup(@RequestBody AppRequest request,
@PathVariable(name="user-id") String userId) {

        AppResponse response = new AppResponse();

        GroupEntity group = new GroupEntity();
        group.setGroupName(request.getName());
        group.setDescription(request.getDescription());

       // Code that causes error when trying to save owner ID
        MemberEntity mem = new MemberEntity();
        mem.setMemberId(Integer.parseInt(userId));
        group.setGroupOwnerId(mem);

        List<Member> members = request.getMembers();

        Set<MemberEntity> storedMembers = new HashSet<>();
        Set<GroupEntity> storedGroups = new HashSet<>();
        storedGroups.add(group);

        for(Member member : members) {
            if(member.getMemberId() != 0) { // existing member
                MemberEntity memberentity = new MemberEntity();
                memberentity.setMemberName(member.getMemberName());
                memberentity.setMemberCity(member.getMemberCity());
                storedMembers.add(memberentity);
                memberentity.setGroups(storedGroups);
                memRepo.save(memberentity);             
            }
            else { // new member
                //some logic
            }

            group.setMembers(storedMembers);
            groupRepo.save(group);
        }
        return null;
    }
}

请求正文将是这样的,

{
  "description": "Funny Group",
  "members": [
    {
      "memberCity": "Mumbai",
      "memberName": "Amit"
    },
    {
      "memberId": 123
    }
  ],
  "name": "My Group"
}

我想要实现的是在创建组时,我想在 REST URL [/createGroup/{user-id}/groups] 中添加用户 ID 作为该组的所有者 ID。为了实现这一点,我手动创建了一个成员实体并将其设置为 groupOwnerId,如下所示,

MemberEntity mem = new MemberEntity();
mem.setMemberId(Integer.parseInt(userId));
group.setGroupOwnerId(mem);

如果我在上面的代码应用程序启动但 groupOwnerId 值设置为 null 这很明显,因为我没有在任何地方设置它。因此,如果我编写上面的代码,应用程序将正确启动。但是当我到达终点时,我得到以下错误,

org.h2.jdbc.JdbcSQLIntegrityConstraintViolationException: Referential integrity constraint violation: "FKB0L8UXRYL2TEVI7BTCMI4BYOD: PUBLIC.""GROUPS"" FOREIGN KEY(GROUP_OWNER_ID) REFERENCES PUBLIC.MEMBERS(MEMBER_ID) (12345)"; SQL statement:
insert into groups (id, description, group_name, group_owner_id) values (null, ?, ?, ?)

我试图弄清楚如何正确地进行映射,以便可以从 URL 映射 groupOwnerId。并且新成员也会使用自动生成的 ID 保存到数据库中。

我目前正在使用 H2 数据库,但最终会迁移到 MySQL 或 Oracle。

请让我知道你们是否可以帮助决定解决此问题的方法。

标签: javadatabasespringh2hibernate-mapping

解决方案


首先,我会为组和用户资源使用以下 URL 模式:

/groups/{groupId}
/users/{userId}

这将允许您分别创建用户和组,因为组可以在没有任何用户的情况下存在,而用户可以在不成为组成员的情况下存在。
像往常一样,对 /groups/ 进行 POST 操作以创建组,对 /users/ 进行 POST 操作以创建用户。
创建组和用户后,我将检索这两个实体(或使用 POST 操作返回的实体)来设置组的组所有者并创建组的 JSON(或 XML)表示。
然后将 JSON 表示放入 URL /groups/{groupId}(在 URL 中插入组的实际 ID),以便将组与新的组所有者保持一致。
希望这可以帮助!


推荐阅读