๐Ÿ’ช(6-3) [Spring&mybatis] ๊ฒŒ์‹œํŒ ๋งŒ๋“ค๊ธฐ - ๊ฒŒ์‹œ๊ธ€ ๋ณด๊ธฐ

์”ฉ์”ฉํ•œ ์กฐ์•ฝ๋Œยท2023๋…„ 2์›” 6์ผ
0

๋ฏธ๋‹ˆํ”„๋กœ์ ํŠธ๐Ÿคน

๋ชฉ๋ก ๋ณด๊ธฐ
18/21

๊ฐœ๋ฐœํ™˜๊ฒฝ

์–ธ์–ด : 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

๊ตฌํ˜„๋‚ด์šฉ

  1. ๋ฉ”์ธํŽ˜์ด์ง€ / ๊ฒŒ์‹œํŒ ๋ชฉ๋ก ๊ตฌํ˜„
  2. CREATE : ๊ฒŒ์‹œ๊ธ€ ์ž‘์„ฑ
  3. READ : ๊ฒŒ์‹œ๊ธ€ ๋ณด๊ธฐ + ์กฐํšŒ์ˆ˜ ์ฆ๊ฐ€

READ : ๊ฒŒ์‹œ๊ธ€ ๋ณด๊ธฐ + ์กฐํšŒ์ˆ˜ ์ฆ๊ฐ€

1. ๊ฒŒ์‹œ๊ธ€ ๋ชฉ๋ก(list.jsp)์—์„œ '๊ธ€ ์ œ๋ชฉ(title)'์„ ๋ˆ„๋ฅด๋ฉด read.do๊ฐ€ ์š”์ฒญ๋˜๊ณ  ๊ฒŒ์‹œ๊ธ€ ๋‚ด์šฉ์„ ๋ณผ ์ˆ˜ ์žˆ๋Š” ํ™”๋ฉด(read.jsp)์œผ๋กœ ์ด๋™

1. read.do ํ˜ธ์ถœํ•  ์ˆ˜ ์žˆ๋„๋ก list.jsp ์ˆ˜์ •

			<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>

2. BoardController

  • list.jsp์—์„œ ์„ ํƒ๋œ ๊ฒŒ์‹œ๊ธ€์˜ num๊ฐ’์„ ๋ฐ›์•„๊ฐ€์•ผ ํ•˜๊ธฐ ๋•Œ๋ฌธ์— ModelAndView๋ฅผ ์ด์šฉ
	@RequestMapping(value="/read.do")
	public ModelAndView readExecute(ModelAndView mav) {
		mav.setViewName("/board/read");
		return mav;
	}

3. read.jsp ์ƒ์„ฑ

  • '๋ชฉ๋ก'์„ ๋ˆ„๋ฅด๋ฉด list.do๊ฐ€ ์‹คํ–‰๋˜๋„๋ก ๋ณ€๊ฒฝ (list.jsp๋กœ ์ด๋™)
<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>

4. ์‹คํ–‰

2. ํ•ด๋‹น ๊ฒŒ์‹œ๊ธ€์˜ num๊ฐ’์„ ๊ฐ€์ ธ์™€์„œ ๊ฒŒ์‹œ๊ธ€ 1๊ฐœ๋ฅผ ๊ฐ€์ ธ์˜ค๊ธฐ

1. BoardMapper.xml

	<select id="read" resultType="board.dto.BoardDTO">
		SELECT * FROM boardBasic
		WHERE ${num}
	</select>

2. BoardDaoImp

	@Override
	public BoardDTO read(int num) {
		return sqlSession.selectOne("board.read");
	}

3. BoardServiceImp

	@Override
	public BoardDTO readProcess(int num) {
		return boardDao.read(num);
	}

4. BoardController

  • readExecute() ์ˆ˜์ •
	@RequestMapping(value="/read.do")
	public ModelAndView readExecute(int num, ModelAndView mav) {
		mav.addObject(boardService.readProcess(num));
		mav.setViewName("/board/read");
		return mav;
	}

5-1. ์‹คํ–‰ -> ์˜ค๋ฅ˜(num๊ฐ’์„ ์ฐพ์ง€๋ชปํ•จ)

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)

5-2. ์˜ค๋ฅ˜ ์ˆ˜์ •

1. BoardMapper.xml

  • parameterType="int" ์ถ”๊ฐ€
  • ์ž˜๋ชป๋œ ์ฟผ๋ฆฌ๋ฌธ ์ˆ˜์ • : WHERE์— 'num='์ด ๋น ์ง
	<select id="read" parameterType="int" resultType="board.dto.BoardDTO">
		SELECT * FROM boardBasic
		WHERE num=${num}
	</select>

2. BoardDaoImp

  • selectOne(์ฟผ๋ฆฌ๋ฌธ, ์กฐ๊ฑด) : ํŒŒ๋ผ๋ฏธํ„ฐ๊ฐ’(์กฐ๊ฑด)์„ ๋„˜๊ฒจ์ฃผ์ง€์•Š์Œ
	@Override
	public BoardDTO read(int num) {
		return sqlSession.selectOne("board.read", num);
	}

3. BoardController

  • service์—์„œ ์ฒ˜๋ฆฌํ•œ ๊ฐ’์„ ๋‹ด์„ "dto"๋ฅผ ์„ค์ •์•ˆํ•จ
  • addObject() : "dto"์— boardService.readProcess(num)๋ฆฌํ„ด๊ฐ’ ๋„ฃ์–ด์ฃผ๊ธฐ
    -> boardService.readProcess(num)๋ฆฌํ„ด๊ฐ’ = ์ฟผ๋ฆฌ๋ฌธ์— ๋Œ€ํ•œ ๋ฐ์ดํ„ฐ๋ฅผ ๋ฐ›์•„์˜ด
    -> "dto"์— ๋‹ด๊ธด ๊ฐ’์€ read.jsp์—์„œ ๋ฐ›์•„์„œ ์‚ฌ์šฉํ•จ
	@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;
	}

4. ์ฃผ์†Œ์— num๊ฐ’์„ ๋„ฃ์–ด์ฃผ์ง€ ์•Š์Œ : list.jsp

<td><a href="read.do?num="${stu.num}>${dto.title}</a></td>

5. ์ƒˆ๋กœ์šด ์˜ค๋ฅ˜ : string์„ int๋กœ ๋ฐ”๊ฟ€ ์ˆ˜ ์—†์Œ..

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: ""]

6. ์ฃผ์†Œ๋กœ ๋ฐ›์„ num์„ 'dto.num'์ด ์•„๋‹Œ stu.num์œผ๋กœ ๋ฐ›์•„์˜ค๊ณ  ์žˆ์—ˆ์Œ... list.jsp

			<c:forEach items="${aList}" var="dto">
				<tr>
					<td>${dto.num}</td>
					<td><a href="read.do?num=${dto.num}">${dto.title}</a></td>

6. ์‹คํ–‰

3. ์กฐํšŒ์ˆ˜ ์ฆ๊ฐ€ ์ฒ˜๋ฆฌ

read.do๊ฐ€ ์‹คํ–‰๋  ๋•Œ readcount๋ฅผ 1์”ฉ ์ฆ๊ฐ€์‹œํ‚ค๊ธฐ
= SELECT์ฟผ๋ฆฌ๋ฌธ์ด ์‹คํ–‰๋˜๊ธฐ ์ „์— UPDATE readcount๋ฅผ ํ•ด์ค˜์•ผํ•จ

1. BoardMapper.xml

์กฐํšŒ์ˆ˜ ์ฆ๊ฐ€์ฒ˜๋ฆฌ๋ฅผ ์œ„ํ•œ UPDATE์ฟผ๋ฆฌ๋ฌธ

	<update id="readcount" parameterType="int">
		UPDATE boardBasic
		SET readcount = readcount+1
		WHERE num=${num}
	</update>

2. BoardDaoImp

	@Override
	public BoardDTO readCount(int num) {
		return sqlSession.selectOne("board.readcount", num);
	}

3. BoardServiceImp

์กฐํšŒ์ˆ˜ ์ฆ๊ฐ€ ์ฒ˜๋ฆฌ(UPDATE์ฟผ๋ฆฌ๋ฌธ) ํ›„์— / ํ•ด๋‹น ๊ฒŒ์‹œ๋ฌผ ๊ฐ€์ ธ์˜ค๊ธฐ(SELECT)์‹คํ–‰

	@Override
	public BoardDTO readProcess(int num) {
		boardDao.readCount(num);
		return boardDao.read(num);
	}

4. ์‹คํ–‰

profile
์”ฉ์”ฉํ•˜๊ฒŒ ๊ณต๋ถ€์ค‘ (22.11~)

0๊ฐœ์˜ ๋Œ“๊ธ€