리액트에서 회원 정보 변경 데이터를 백엔드로 전달해 업데이트 로직을 구현하던 중, xml 파일의 쿼리문에서
[MyBatis] Parameter 'newUserName' not found. Available parameters are [arg1, arg0, param1, param2] 라는 오류가 발생하였다.
<update id="changeUserName" parameterType="string">
UPDATE user
SET userName = #{newUserName}
WHERE userId = #{userId}
</update>
분명 'newUserName' 데이터가 정상적으로 전달되었고, 쿼리문도 틀린 부분이 없어 헤매다가 'Parameter' 에서 힌트를 찾을 수 있었다.
원인
변경 전 메소드
public int changeUserName(@RequestBody Map<String, String> requestData) {
//requestData = {userId : 'shxxxx' , newUserName : '성훈'}
string userId = requestData.get("userId");
string newUserName = requestData.get("newUserName");
int result = infoService.changeUserName(userId, newUserName); //문제의 원인
return result;
}
requestData 객체에서 userId와 newUserName 변수에 값을 치환 해 두 개의 파라미터를 전달하고 있는데,
MyBatis를 이용한 SQL Mapper의 메소드는 하나의 파라미터만을 읽으므로 , 파라미터의 개수가 2개 이상일 때 오류가 발생 한다.
-> 하나의 파라미터만 읽기 때문에 2개 이상의 파라미터를 전달할 경우 해당데이터가 어떤 것인지를 명시하지 않으면 에러 러가 발생하는 것이었다.
원인을 찾은 후 검색해보니, 파라미터 이슈를 해결하는 여러 가지 방법들이 있었다.
1. @Param 어노테이션으로 파라미터 전달 값을 명시
2. 변수명을 arg로 맞추어 사용하기 - 파라미터 입력 순서대로 (arg0, arg1, ..) -> Available parameters are [arg1, arg0, param1, param2] 라고 친절히 알려준다.
3. 변수명을 param으로 맞추어 사용하기
- 파라미터 입력 순서대로 사용(param1, param2, ..)
4. 파라미터를 1개에 담아서 사용하기
- 2개의 파라미터를 Map이나 VO에 담아서 하나의 파라미터로 보내 사용
-> 내가 선택한 해결 방법이다. 나는 Map을 통해 데이터를 전달하고 있었고, 리액트로 예외 처리를 구현했기 때문에 Map을 그대로 쓰면 편하게 로직을 구현할 수 있기 때문. (백엔드에서 예외 처리까지 구현하려고 노력해봐야겠다.)
해결
변경 후 메소드
public int changeUserName(@RequestBody Map<String, String> requestData) {
int result = infoService.changeUserName(requestData); //Map 형태를 그대로 전달함
return result;
}
쿼리문의 ParameterType도 Map으로 수정해주었다.
<update id="changeUserName" parameterType="map">
UPDATE user
SET userName = #{newUserName}
WHERE userId = #{userId}
</update>
수정 후 정상적으로 기능이 구현되었고, 문제를 해결할 수 있었다!
Parameter not found 이슈가 발생했다면, 위의 4가지 방법 중 적절한 방법을 택해 해결하면 좋을 듯 싶다. 👍
댓글