๊ฐ๋ฐํ๊ฒฝ
์ธ์ด : JAVA (JDK 11)
์๋ฒ : Apache Tomcat 9.0
ํ๋ ์์ํฌ : Spring Framework 3.9.18, MyBatis 3.5.8, Bootstrap 5.2.3
DB : OracleXE 11gR2
IDE : sts-3.9.18.RELEASE, SQL Developler
๊ตฌํ๋ด์ฉ
- ๋ฉ์ธํ์ด์ง / ๊ฒ์ํ ๋ชฉ๋ก ๊ตฌํ
- CREATE : ๊ฒ์๊ธ ์์ฑ
- READ : ๊ฒ์๊ธ ๋ณด๊ธฐ + ์กฐํ์ ์ฆ๊ฐ
<c:forEach items="${aList}" var="dto">
<tr>
<td>${dto.num}</td>
<td><a href="read.do">${dto.title}</a></td>
<td>${dto.writer}</td>
<td>${dto.regdate}</td>
<td>${dto.readcount}</td>
</tr>
</c:forEach>
@RequestMapping(value="/read.do")
public ModelAndView readExecute(ModelAndView mav) {
mav.setViewName("/board/read");
return mav;
}
<body>
<table>
<tr><th>์์ฑ์</th><td>${writer}</td><th>์์ฑ์ผ</th><td>${regdate}</td></tr>
<tr><th>์ ๋ชฉ</th><td>${title}</td><th>์กฐํ์</th><td>${readcount}</td></tr>
<tr><th>๋ด์ฉ</th><td>${content}</td></tr>
</table>
<a href="list.do">๋ชฉ๋ก</a>
</body>
<select id="read" resultType="board.dto.BoardDTO">
SELECT * FROM boardBasic
WHERE ${num}
</select>
@Override
public BoardDTO read(int num) {
return sqlSession.selectOne("board.read");
}
@Override
public BoardDTO readProcess(int num) {
return boardDao.read(num);
}
@RequestMapping(value="/read.do")
public ModelAndView readExecute(int num, ModelAndView mav) {
mav.addObject(boardService.readProcess(num));
mav.setViewName("/board/read");
return mav;
}
HTTP ์ํ 500 โ ๋ด๋ถ ์๋ฒ ์ค๋ฅ
ํ์
์์ธ ๋ณด๊ณ
๋ฉ์์ง Request processing failed; nested exception is java.lang.IllegalStateException: Optional int parameter 'num' is present but cannot be translated into a null value due to being declared as a primitive type. Consider declaring it as object wrapper for the corresponding primitive type.
์ค๋ช
์๋ฒ๊ฐ, ํด๋น ์์ฒญ์ ์ถฉ์กฑ์ํค์ง ๋ชปํ๊ฒ ํ๋ ์๊ธฐ์น ์์ ์กฐ๊ฑด์ ๋ง๋ฅ๋จ๋ ธ์ต๋๋ค.
์์ธ
org.springframework.web.util.NestedServletException: Request processing failed; nested exception is java.lang.IllegalStateException: Optional int parameter 'num' is present but cannot be translated into a null value due to being declared as a primitive type. Consider declaring it as object wrapper for the corresponding primitive type.
org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:1014)
org.springframework.web.servlet.FrameworkServlet.doGet(FrameworkServlet.java:898)
javax.servlet.http.HttpServlet.service(HttpServlet.java:670)
org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:883)
javax.servlet.http.HttpServlet.service(HttpServlet.java:779)
org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:53)
org.springframework.web.filter.CharacterEncodingFilter.doFilterInternal(CharacterEncodingFilter.java:201)
org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:119)
๊ทผ๋ณธ ์์ธ (root cause)
parameterType="int"
์ถ๊ฐ <select id="read" parameterType="int" resultType="board.dto.BoardDTO">
SELECT * FROM boardBasic
WHERE num=${num}
</select>
@Override
public BoardDTO read(int num) {
return sqlSession.selectOne("board.read", num);
}
addObject()
: "dto"
์ boardService.readProcess(num)๋ฆฌํด๊ฐ ๋ฃ์ด์ฃผ๊ธฐ @RequestMapping(value="/read.do")
public ModelAndView readExecute(int num, ModelAndView mav) {
System.out.println(num);
mav.addObject("dto", boardService.readProcess(num));
mav.setViewName("/board/read");
return mav;
}
<td><a href="read.do?num="${stu.num}>${dto.title}</a></td>
WARN : org.springframework.web.servlet.mvc.support.DefaultHandlerExceptionResolver - Resolved [org.springframework.web.method.annotation.MethodArgumentTypeMismatchException: Failed to convert value of type 'java.lang.String' to required type 'int'; nested exception is java.lang.NumberFormatException: For input string: ""]
<c:forEach items="${aList}" var="dto">
<tr>
<td>${dto.num}</td>
<td><a href="read.do?num=${dto.num}">${dto.title}</a></td>
read.do๊ฐ ์คํ๋ ๋ readcount๋ฅผ 1์ฉ ์ฆ๊ฐ์ํค๊ธฐ
= SELECT์ฟผ๋ฆฌ๋ฌธ์ด ์คํ๋๊ธฐ ์ ์ UPDATE readcount๋ฅผ ํด์ค์ผํจ
์กฐํ์ ์ฆ๊ฐ์ฒ๋ฆฌ๋ฅผ ์ํ UPDATE์ฟผ๋ฆฌ๋ฌธ
<update id="readcount" parameterType="int">
UPDATE boardBasic
SET readcount = readcount+1
WHERE num=${num}
</update>
@Override
public BoardDTO readCount(int num) {
return sqlSession.selectOne("board.readcount", num);
}
์กฐํ์ ์ฆ๊ฐ ์ฒ๋ฆฌ(UPDATE์ฟผ๋ฆฌ๋ฌธ) ํ์ / ํด๋น ๊ฒ์๋ฌผ ๊ฐ์ ธ์ค๊ธฐ(SELECT)์คํ
@Override
public BoardDTO readProcess(int num) {
boardDao.readCount(num);
return boardDao.read(num);
}