"could not execute statement; SQL [n/a]; constraint [\"PRIMARY KEY ON PUBLIC.VOTE_ITEM(VOTE_ITEM_ID) [1, 0, STRINGDECODE('\ucc2c\uc131'), 'abcd']\"; SQL statement:\ninsert into vote_item (cnt, content, vote_id, vote_item_id) values (?, ?, ?, ?) [23505-200]]; nested exception is org.hibernate.exception.ConstraintViolationException: could not execute statement"
Spring Boot 컨트롤러 테스트를 진행하던 중 save테스트를 진행하던 과정에서 위와 같은 error가 발생하기 시작했습니다.
메시지를 읽어보면 VOTE_ITEM의 PRIMARY KEY가 문제를 일으키고 있다고 생각이 됩니다. 그 전에 일단 현재 어떤 상황인지 확인을 해보기로 하였습니다.
일단 테스트를 위해 data.sql을 이용해서 먼저 데이터를 입력해 놓았습니다. 이 프로젝트는 투표게시판이며 는 Vote(투표)와 투표의 항목이 되는 VoteItem(투표항목)을 미리 입력해 놓았습니다.
data.sql
INSERT INTO USERS VALUES('fftl');
INSERT INTO VOTE(vote_id, board_id, title, description, dead_line, user_id) VALUES(
'abcd', 1, '제목입니다.', '찬성 혹은 반대?', '2021-12-30 20:00:01', 'fftl');
INSERT INTO VOTE_ITEM(vote_item_id, content, cnt, vote_id) VALUES(1, '찬성', 0, 'abcd');
INSERT INTO VOTE_ITEM(vote_item_id, content, cnt, vote_id) VALUES(2, '반대', 0, 'abcd');
@DisplayName("투표 등록 테스트")
@Test
void saveVote() throws Exception{
//일단 VoteItem을 만들고 Items를 만들어 Vote 정보에 넣어 한번에 데이터를 입력합니다.
JsonObject Item1 = new JsonObject();
Item1.addProperty("content", "찬성");
Item1.addProperty("voteId", "osie");
JsonObject Item2 = new JsonObject();
Item2.addProperty("content", "반대");
Item2.addProperty("voteId", "osie");
JsonArray Items = new JsonArray();
Items.add(Item1);
Items.add(Item2);
JsonObject obj = new JsonObject();
obj.addProperty("voteId","osie");
obj.addProperty("boardId",2L);
obj.addProperty("title","제목");
obj.addProperty("description","내용");
obj.add("voteItemRequest", Items);
obj.addProperty("deadLine","2021-12-30 23:27:00");
obj.addProperty("userId","fftl");
ResultActions actions = mvc.perform(
post("/vote")
.contentType(MediaType.APPLICATION_JSON)
.accept(MediaType.APPLICATION_JSON)
.characterEncoding("UTF-8")
.header("x-user-id", "fftl")
.content(String.valueOf(obj)));
actions
.andDo(print())
.andExpect(status().isOk())
.andExpect(jsonPath("$.success").value(true))
.andExpect(jsonPath("$.data").isString())
.andExpect((jsonPath("$.message").doesNotExist()));
}
문제가 발생하고 일단 data.sql에 있던 INSERT INTO USERS VALUES('fftl');
를 제외한 데이터 입력 sql문을 지운 뒤 실행을 해보았는데 그 때에는 정상적으로 데이터 입력 테스트를 통과하는 것을 확인했습니다. 즉 데이터를 완전 처음 입력 할 때에는 문제가 발생하지 않는다는 것 이었습니다.
위와 같은 현상을 발견하자 VoteItemId를 자동생성하는 @GeneratedValue가 문제가 있는가 살펴보았고 이 때 저는 @GeneratedValue의 strategy를 설정하지 않고 기본값으로 놔두었습니다. 찾아보니 @GeneratedValue의 default strategy값은 AUTO였습니다.
결론 적으로는 이 strategy를 IDENTITY로 변경하니 정상적으로 작동을 하였습니다. 이에 대한 원인과 결과를 더 찾아서 추가할 예정입니다.
내용을 추가 할 예정입니다.