Отображение OneToOne: нарушение ограничения ссылочной целостности - PullRequest
1 голос
/ 17 октября 2019

Я занимаюсь разработкой REST API с использованием данных пружины JPA, и мне нужна некоторая помощь.

Мой 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

My GroupEntity:

@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

My MemberEntity:

@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] в качестве идентификатора владельца для этой группы. Чтобы достичь этого, я вручную создаю сущность-член и устанавливаю ее как groupOwnerId, как показано ниже,

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

Если я прокомментирую выше, фрагмент кода приложения загружается, но значение groupOwnerId устанавливается как ноль, что очевиднопоскольку я не устанавливаю это нигде. Поэтому, если я напишу приведенный выше код, приложение загрузится правильно. Но когда я достигаю конечной точки, я получаю ошибку ниже,

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, ?, ?, ?)

Я пытаюсь выяснить, КАК я могу сделать сопоставление правильно, чтобы я мог сопоставить groupOwnerId из URL. А также новые участники сохраняются в базе данных с автоматически сгенерированными идентификаторами.

Я сейчас использую базу данных H2, но в конечном итоге перееду на MySQL или Oracle.

Пожалуйста, дайте мне знать, если выребята могут помочь решить подход к этому вопросу.

1 Ответ

0 голосов
/ 17 октября 2019

Прежде всего, я бы использовал следующие шаблоны URL для ресурсов группы и пользователя:

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

Это позволит вам создавать пользователей и группы отдельно, поскольку группа может существовать без каких-либо пользователей, а пользователь может существовать, не будучи членом группы. Как обычно, операция POST для / groups / для создания группы и POST для / users / для создания пользователя. После создания группы и пользователя я извлекаю обе сущности (или использую сущности, возвращаемые операциями POST), чтобы установить владельца группы и создать представление группы в формате JSON (или XML). Представление JSON затем помещается в URL / groups / {groupId} (с фактическим идентификатором группы, вставленным в URL), чтобы сохранить группу с новым владельцем группы. Надеюсь, это поможет!

...