useAffectedRows=true
옵션으로 Hibernate 애플리케이션 기동 실패한 썰업무 중에 별거 아닌 설정 하나가 기동 장애라는 결과를 가져와, 기억할 겸 정리해둡니다. 혹시 저와 같은 문제를 겪는 분이 있다면 도움이 되길 바라며...
프로젝트에서 MySQL 데이터베이스를 사용하고 있었고, JDBC URL에 useAffectedRows=true
옵션이 설정돼 있었습니다. 사실 이 옵션은 크게 신경 쓰지 않고 넘어갔던 부분인데, 갑자기 Hibernate가 애플리케이션을 기동하면서 Batch update returned unexpected row count from update [0]: actual row count: 0; expected: 1
쿼리에서 오류를 내뿜는 겁니다.
이전에 잘 돌던 코드가 갑자기 안 돌아가니까 당황스러웠죠. 특별히 변경된 부분도 없었고요. 로그를 뒤지고 설정을 하나씩 뜯어보다가 결국 원인은 이 useAffectedRows=true
옵션에 있다는 걸 알게 되었습니다.
알고 보니 useAffectedRows=true
는 MySQL의 UPDATE
쿼리가 데이터를 업데이트할 때 실제로 바뀐 행만 영향을 받은 행 수로 처리하도록 만드는 옵션이더군요. 좀 더 구체적으로 설명하자면:
useAffectedRows=false
상태에선, 데이터가 실제로 바뀌지 않아도 UPDATE
쿼리가 영향을 받은 행 수를 1로 반환합니다. 쉽게 말해 "업데이트 시도했다!" 정도로 처리하는 거죠.useAffectedRows=true
로 설정하면, 데이터가 바뀌지 않으면 영향을 받은 행 수를 0으로 반환합니다. Hibernate는 여기서 혼란을 느끼게 됩니다.사실, 에러 로그에서도 정직하게 설명이 되있었습니다.
Batch update returned unexpected row count from update [0]: actual row count: 0; expected: 1
Hibernate는 업데이트 성공 여부를 반환된 행 수로 판단하기 때문에, useAffectedRows=true
옵션이 활성화돼서 데이터가 바뀌지 않으면 0이 반환됩니다. Hibernate는 이걸 업데이트 실패로 오해해서 예외를 발생시키고, 결국 애플리케이션이 기동에 실패하는 거죠.
useAffectedRows=false 로 변경 또는 제거.
mysql 은 다른 DB 와 다르게 JDBC URL 에 옵션이 많이 붙기 때문에 정확히 어떠한 설정인지 알고 쓰는게 좋을 거 같습니다.
에러 로그는 거짓말 하지 않습니다..