API는 언뜻보면 참 간단해 보이는 구조이지만, 내부적으로 하나라도 엉키면 아무것도 동작하지 않습니다. 이번에는 여러가지 error중 한가지를 보도록 하겠습니다.
[Error]
Servlet.service() for servlet [dispatcherServlet] in context with path [] threw exception [Request processing failed; nested exception is org.mybatis.spring.MyBatisSystemException: nested exception is org.apache.ibatis.binding.BindingException: Parameter 'mydto' not found. Available parameters are [smDTO, stationName, param1, param2]] with root cause
아무리 살펴봐도 난 잘못된게 없는데, 도데체 에러가 왜 발생하는지 모르겠다... mydto는 무엇이며, 난 parameter로 다 넣었는데 뭐가 문제라는거야?? test 예제는 아래와 같습니다.
[Mapper.java]
@Mapper
public interface UserMapper {
ArrayList<UserDTO> selectUser();
ArrayList<StationMiseDTO> selectStationMise();
StationMiseDTO selectStationMiseById(String stationName);
Integer insertStationMise(@Param("mydto") StationMiseDTO smDTO);
Integer updateStationMise(StationMiseDTO smDTO, String stationName);
Integer deleteStationMise(String stationName);
}
[Mapper.xml]
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.example.ayoteralab.main.mapper.UserMapper">
<select id="selectUser" resultType="com.example.ayoteralab.main.dto.UserDTO">
<![CDATA[
SELECT
*
FROM USER
]]>
</select>
<select id="selectStationMise" resultType="com.example.ayoteralab.main.dto.StationMiseDTO">
<![CDATA[
SELECT
STATION_NAME,
NO2_VALUE,
O3_VALUE,
PM10_VALUE,
PM25_VALUE,
DATE_TIME
FROM STATION_MISE
]]>
</select>
<select id="selectStationMiseById" resultType="com.example.ayoteralab.main.dto.StationMiseDTO">
<![CDATA[
SELECT
STATION_NAME,
NO2_VALUE,
O3_VALUE,
PM10_VALUE,
PM25_VALUE,
DATE_TIME
FROM STATION_MISE
WHERE STATION_NAME = #{stationName}
]]>
</select>
<insert id="insertStationMise" parameterType="com.example.ayoteralab.main.dto.StationMiseDTO">
<![CDATA[
INSERT INTO STATION_MISE
(STATION_NAME, NO2_VALUE, O3_VALUE, PM10_VALUE, PM25_VALUE, DATE_TIME)
VALUES
(#{mydto.stationName}, #{mydto.no2Value}, #{mydto.o3Value}, #{mydto.pm10Value}, #{mydto.pm25Value}, #{mydto.dateTime})
]]>
</insert>
<update id="updateStationMise" parameterType="java.lang.String">
<![CDATA[
UPDATE STATION_MISE
SET PM10_VALUE = #{mydto.pm10Value}, PM25_VALUE = #{mydto.pm25Value}
WHERE STATION_NAME = #{stationName}
]]>
</update>
<delete id="deleteStationMise" parameterType="java.lang.String">
<![CDATA[
DELETE FROM STATION_MISE
WHERE STATION_NAME = #{stationName}
]]>
</delete>
</mapper>
이 길다긴 코드에서 어떻게 찾을 수 있을까?? 이런건 현장에서 보면... 1/10도 안되는 참으로 짧은 코드이지요... 우선은 어떤 요청을 했을때 발생했는지 찾습니다.
저는 http://localhost:8080/test/stationMise/han river에 method put으로 했을때 발생했기 때문에... Controller에 put으로 되어있는 부분을 찾아봅니다. 이제 service와 mapper를 쭉 따라갑니다. 그렇게 되면 뒤에 2개의 코드가 나오겠죠??
그 중에서 put인 update를 봅니다.... mapper.xml을 보면 이상이 없어보입니다. DTO로 보낸 정보를 잘 원하는 위치에 배치했고...
그럼 mapper.java를 봅니다. 이상한 점이 보이시나요??
mapper.xml에서는 #{mydto.pm10Value} 처럼... DTO에 @Param으로 alias해서 해당 이름을 사용해서 parameter정보는 대입하였습니다. 하지만... mapper.java에서는 해당 DTO에 대해서 @Param을 정해주지 않았습니다.
따라서...
[AS-IS] Integer updateStationMise(StationMiseDTO smDTO, String stationName);
[To-Be] Integer updateStationMise(@Param("mydto") StationMiseDTO smDTO, String stationName);
이렇게 해주면... error가 사라지게됩니다.
-Ayotera Lab-
댓글