[트러블 슈팅] nct club project

2023. 10. 7. 16:44
728x90

1. 데이터 베이스 테이블에 여러 개의 레코드 삽입 시, 외래 키 시퀀스 중복 및 무결성 문제 해결

1) 문제 발생 상황 1. nct 멤버 insert SQL문에 두 개의 테이블에 삽입 시 마이바티스를 통한 다중 insert를 하려고 함.
> 그러나, DataIntegrityViolationException 발생 
<insert id="insertMemberInfo" statementType="STATEMENT">
    <![CDATA[
        INSERT INTO nctmembers (memberId, name, birthdate, nationality, position, mbti, image, regdate)
        VALUES (NCTMEMBERS_SEQ.NEXTVAL, #{name}, #{birthdate}, #{nationality}, #{position}, #{mbti}, #{image}, SYSDATE);
        
        <foreach collection="groupList" item="group" separator=";">
            INSERT INTO nctgroups (groupId, groupName, memberRefId)
            VALUES (NCTGROUPS_SEQ.NEXTVAL, #{group}, NCTMEMBERS_SEQ.CURRVAL)
        </foreach>
    ]]>
</insert>
2) 문제 발생 원인 버전이 맞지 않아 다중 insert SQL문이 제대로 적용되지 않음. 

3) 원인 해결 방법 insert문을 두개로 나눔.
<!-- Insert member -->
   <insert id="insertMember">
     INSERT INTO nctmembers (memberId, name, birthdate, nationality, position, mbti, image, regdate)
     VALUES (NCTMEMBERS_SEQ.NEXTVAL, #{name}, #{birthdate}, #{nationality}, #{position}, #{mbti}, #{image}, SYSDATE)
   </insert>

<!-- Insert groups for member -->
   <insert id="insertGroupsForMember">
      <foreach collection="groupList" item="group" index="index" separator=",">
          INSERT INTO nctgroups (groupId, groupName, memberRefId)
          VALUES (NCTGROUPS_SEQ.NEXTVAL, #{group}, NCTMEMBERS_SEQ.CURRVAL)
       </foreach>
   </insert>
1) 문제 발생 상황 2 nct 멤버 insert 삽입 SQL문에 두 개의 컬럼에 시퀀스 값을 넣어야 해서 value값에 시퀀스.nextval과 currval을 각각 넣었다.
> 그러나, 지속적으로 DataIntegrityViolationException 혹은 DuplicateKeyException 발생 
2) 문제 발생 원인2 1. 한 멤버는 여러 그룹에 소속될 수 있다. > 엔시티 그룹 테이블 생성 & 엔시티 멤버 테이블의 memberId를 외래키로 가져옴.
2. 그러므로 INSERT문을 쓸 때에 두 개의 테이블에 삽입을 해주어야 함. (INSERT INTO nctmembers & INSERT INTO nctgroups) 
3. 이 때 memberId는 nctmembers 테이블에 넣은 값으로 가져오기 위해 SEQ.CURRVAL을 사용하는데  foreach구문을 돌면서 시퀀스.nextval은 계속 같은 값이 INSERT 되면서 문제가 생겼다. 데이터 무결성 제약조건에 위반되는 것.
3) 원인 해결 방법2 1. foreach문(다중 insert문)을 groupName에만 적용시킨다. > A.* FROM ( <foreach collection...></foreach>)A 설정 활용
2. memberId는 시퀀스.currval을 사용해야 하는데, 이걸 쉽게 가져오기 위해서 useGeneratedKeys 키 설정을 활용해 쉽게 멤버아이디 값을 받아오도록 한다.
> useGeneratedKeys="true" keyProperty="id" keyColumn="memberId"
<!-- Insert member -->
   <insert id="insertMember" useGeneratedKeys="true" keyProperty="id" keyColumn="memberId">
       INSERT INTO nctmembers (memberId, name, birthdate, nationality, position, mbti, image, regdate)
       VALUES (NCTMEMBERS_SEQ.NEXTVAL, #{name}, #{birthdate}, #{nationality}, #{position}, #{mbti}, #{image}, SYSDATE)
   </insert>

<!-- Insert groups for member -->
    <insert id = "insertGroupsForMember" parameterType = "java.util.List">
          INSERT INTO nctgroups (groupId, memberRefId, groupName)
          SELECT NCTGROUPS_SEQ.NEXTVAL, #{id}, A.* FROM (
                  <foreach collection = "groupList" item = "group" separator = "UNION ALL">
                                 SELECT #{group}
                                 FROM DUAL
                  </foreach>) A
    </insert>
4) 적용 및 해결
여부 확인
적용했더니 foreach문은 정상적으로 딱 groupName에만 적용되었고, keyProperty id를 활용해 #{id} 로 간단하게 표현하니 오류 해결
5) 예방 방안 테이블 여러 개에서 외래키 시퀀스를 입력할 때에는 각별한 유의가 필요하다. 특히나 시퀀스는 절대 겹치지 않도록 만들어놓은 장치이기 때문에 이를 활용해서 반복적으로 입력할 때에는 그 반복으로 인해 중복이 생기지 않도록 해야 한다. 

 

728x90

BELATED ARTICLES

more