D+46::객체생성_어노테이션(@)/의존성주입(Dependance Injection)/스퀀스(Sequence)/스프링부트:게시판목록조회/게시글등록/상세보기

Am.Vinch·2022년 8월 30일
0

20220830_Tue

스프링 특징은?

  • 스프링은 객체를 직접 생성하지 않고(new x), 스프링이 자체적으로 객체를 생성하도록 작성(선언만!)

스프링 객체생성 방법 및 순서

  • 1. 스프링이 프로젝트 시작과 동시에 필요한 객체를 먼저 생성할 수 있도록 설정해야한다.
    • 1) 객체를 생성하고자 하는 클래스는 반드시 기본 패키지 내에 선언되어야한다. :기본패키지는 최초 프로젝트 생성시 만들어지는 최초의 패키지를 의미함
      (cf. 우리가 만든 프로젝트 board 의 기본패키지도 kh.study.board이기때문에 board패키지 내 클래스에서 선언되어있어야한다 )
    • 2) 객체를 만들고자 하는 클래스에 객체생성 코드를 작성한다. -> 객체를 만들고자 하는 클래스 위에(밖에) 어노테이션을 사용해야한다.
      • 객체생성 어노테이션 4가지
      • @Component : 초창기사용.요즘은 사용x 사용해도 오류발생x
      • @Controller : 컨트롤러에 대한 객체생성
      • @Service : 서비스에 대한 객체생성
      • @Repository: 나중에 배울것!
        : 위 4개의 어노테이션을 사용하면 객체를 생성하는데, 생성되는 개체명은 클래스명의 앞글자만 소문자로 바꾼 이름으로 자동으로 객체명 정의된다.
        • ex1) 자동 객체명 생성(소문자)
        @Controller 
        pulbic class TestController{} 
       자동 객체명 소문자로 생성 -> TestController **testController** = new TestController();
      • ex2) 수동 객체명 생성(괄호안 별도 지정)
       @Controller("controller")
       pulbic class TestController{} 
       별도 객체명 지정시,괄호 안 객체명으로 생성-> TestController **controller** = new TestController();
  • 2.프로젝트 생성과 동시에 만들어진 객체를 적절하게 "의존성 주입"(DI)시키는 코드를 작성해야한다.
    • 1) 의존성 주입이 필요한 객체명 위에 어노테이션을 적용하여 코드를 작성한다(만들어진 객체를 가지고 내가 필요한 객체를 넣어준다)
      • @Autowired : 자료형을 기준으로 의존성 주입을 시킬 객체를 판단한다.
      • @Resource : name값 기준으로 의존성 주입을 시킬 객체를 판단한다.
    • 2) 상황을 들어 예시를 들어보자.
      프로젝트 시작과 동시에 자동으로 내부적으로 만들어진 객체 정보는 다음과 같다.
      • a. BoardController controller = new BoardController();
      • b. BoardService service = new BonardService();
      • c. BoardDTO board = new BoardDTO();
        - d. BoardService service1 = new BonardService();
        public class Test1{
        	@autowired -> 해석하자면 내부적으로 private BoardDTO dto = board; 진행된다.
            private BoardDTO dto;
         * 오류발생코드: b,d의 자료형 중복
         @autowired 
         private BoardService service;
        * 오류발생 x 
        : @Resource를 사용하면 실제로 우리가 만들어진 객체 중에 (a~d) service 로 만들어진 객체에 넣어주세요!
       @Resource(name="service")
        private BoardService service;
		* 오류발생코드: controller 이름의 객체명은 있지만 자료형 불일치!!!
        @Resource(name="controller")
        private BoardService service;
            * 오류발생코드: 만들어진 객체 중에(a~d) 없기때문
            @autowired
            private MemberDTO member;
        }

실습내용

  • 게시글 목록페이지에 게시글 목록 데이터를 표로 띄우세요
  • 게시글 목록페이지 하단에 글쓰기 버튼 생성
  • 글쓰기 버튼 클릭 시 글쓰기 양식페이지로 이동
  • 글 데이터를 적절히 입력 후 '등록' 버튼 클릭하면 실제 디비 insert 진행
  • insert 성공시, alert으로 '글등록' 띄고, 게시글 목록페이지로 이동
  • 제목을 클릭하면 게시글 정보에 대한 모든 정보를 띄우는 상세보기 페이지로 이동
  • 생성 파일 목록
    • board_list.html
    • reg_board.html
    • detail_board.html
    • BoardController
    • BoardService
    • BoardServiceImpl
    • board-mapper

DB_스퀀스(Sequence)

  • 스퀀스(Sequence)
CREATE SEQUENCE TEST_SEQ 
START WITH 1 -- 1부터 시작
INCREMENT BY 1; -- 1씩 증가

  • 테이블 생성 SPRING_BOARD
  CREATE TABLE SPRING_BOARD (
    BOARD_NUM NUMBER PRIMARY KEY-- 1,2,3,4,5..
    , TITLE VARCHAR2(100) NOT NULL
    , CONTENT VARCHAR2(100)
    , WRITER VARCHAR2(100) NOT NULL
    , CREATE_DATE DATE DEFAULT SYSDATE  
);
  • 테이블 조회
SELECT * 
FROM SPRING_BOARD
ORDER BY BOARD_NUM DESC;
  • 스퀀스(Sequence)
CREATE SEQUENCE TEST_SEQ 
START WITH 1 -- 1부터 시작
INCREMENT BY 1; -- 1씩 증가
  • NEXT 먼저 실행 후, CURR 실행해야 값이 뜬다!
SELECT TEST_SEQ.NEXTVAL FROM DUAL; -- 조회실행할때마다 1씩 증가됨
SELECT TEST_SEQ.CURRVAL FROM DUAL; -- 현재 VALUE 조회
  • 스퀀스 값을 초기화 시키는 코드
    ALERT SEQUENCE TEST_SEQ INCREMENT BY 1;
  • 스퀀스 생성 (BAORD_NUM)
CREATE SEQUENCE BOARD_NUM_SEQ
START WITH 1
INCREMENT BY 1;
  • 테이블 데이터 삽입(게시글 등록)
INSERT INTO SPRING_BOARD (
			BOARD_NUM
			, TITLE
			, CONTENT
			, WRITER
) VALUES(
			TEST_SEQ.NEXTVAL 
			, '제목1'
			, '내용1'
			, '작성자1'
) ;
  • 상세조회 쿼리문
SELECT BOARD_NUM
			, TITLE
			, WRITER
			, CONTENT
			, CREATE_DATE
		FROM SPRING_BOARD
		WHERE TITLE = '제목1';   

스프링 부트

  • board_list.html

    <!DOCTYPE html>
    <html xmlns:th="http://www.thymeleaf.org">
    <head>
    <meta charset="UTF-8">
    <title>Insert title here</title>
    <style type="text/css">
    table{
    	width: 800px;
    	margin: 0 auto;
    	border-collapse: collapse;
    	border: 1px solid black;
    }
    table>thead>tr:first-child{
    	margin-bottom: 10px;
    }
    tr,td{
    	border-collapse: collapse;
    	border: 1px solid black;
    }
    </style>
    </head>
    <body>
    	<table border="1">
    		<thead>
    		<tr>
    			<td>게시글 번호</td>
    			<td>제목</td>
    			<td>작성자</td>
    			<td>작성일</td>
    			<!-- 리스트크기 데이터 갖고오는 방법 2가지-->
    			<!-- <td th:text="${#lists.size(boardList)}"></td>
    			<td th:text="${boardList.size()}"></td> -->
    		</tr>
    		</thead>
    
    		<tbody>
    		<th:block th:if="${#lists.size(boardList) == 0}">
    			<tr>
    				<td colspan="4">게시글이 없습니다.</td>
    			</tr>
    		</th:block>
    		<th:block th:unless="${#lists.size(boardList) == 0}">
    			<tr th:each="board : ${boardList}"><!-- 컨트롤러에서 넘긴 그대로:boardList -->
    				<td th:text="${board.boardNum}"></td>
    				<td>
    					<a th:href="@{'/board/detail/' + ${board.boardNum}}">
    	                    <span th:text="${board.title}"></span>
                      </a>
    				</td>
    				<td th:text="${board.writer}"></td>
    				<td th:text="${board.createDate}"></td>
    			</tr>		
    		</th:block>
    		</tbody>
    
    	</table>
    <div align="center">
    <!-- location.href 이동시, /board/... 식으로(컨트롤러이동) 작성해야한다! -->
    	<input class="btn" type="button" value="글쓰기" onclick ="location.href='/board/regBoard';">
    </div>
    </body>
    </html>
  • reg_board.html

    <!DOCTYPE html>
    <html xmlns:th="http://www.thymeleaf.org"><!-- jsp에서 foreach문 사용할때 lib태그 사용하는 것과 같다.앞으로 html 만들때는 사용해야한다. 원래 html만들때 next누르고 별도로 생성한 htnl_thymeleaf를 선택하면 자동생성된다-->
    <head>
    <meta charset="UTF-8">
    <title>Insert title here</title>
    </head>
    <body>
    <form action="/board/regBoard" method="post"><!--form 하면 반드시 submit 필요 (onclick삭제)  -->
    	<table>
    		<tr>
    			<td>제목</td>	
    			<td><input name="title" type="text" ></td>	
    		</tr>
    		<tr>
    			<td>작성자</td>	
    			<td><input name="writer" type="text" ></td>	
    		</tr>
    		<tr>
    			<td>내용</td>	
    			<td><textarea rows="3" cols="50" name="content"></textarea></td>	
    		</tr>
    	</table>
    <div align="center">
    	<input type = "submit" value = "글등록"  >
    </div>
    </form>
    </body>
    </html>
  • detail_board.html

    <!DOCTYPE html>
    <html xmlns:th="http://www.thymeleaf.org"><!-- jsp에서 foreach문 사용할때 lib태그 사용하는 것과 같다.앞으로 html 만들때는 사용해야한다. 원래 html만들때 next누르고 별도로 생성한 htnl_thymeleaf를 선택하면 자동생성된다-->
    <head>
    <meta charset="UTF-8">
    <title>Insert title here</title>
    </head>
    <body>
    상세보기 페이지입니다.
    <div>
    <input type="button" class="btn" value="글쓰기 수정"> <!--> -->
    	<input type="button" class="btn" value="글쓰기 삭제"> <!--> -->
    </div> 
    </body>
    </html>
  • BoardController

 package kh.study.board.controller;

import javax.annotation.Resource;

import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.DeleteMapping;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.PutMapping;
import org.springframework.web.bind.annotation.RequestMapping;

import kh.study.board.service.BoardService;
import kh.study.board.vo.BoardVO;


@Controller
@RequestMapping("/board")// "/board"로 시작하면 무조건 컨트롤러 실행하겠다
public class Boardcontroller {
	//boardService 라는 이름으로 만들어진 개체를 로드해서 
	//"의존성 주입"을 실행한다
	//@Resource는 @autoWired와 비슷하지만 자료형이 같은 객체가 아니라 
	//name값이 같은 변수명을 가져와서 데이터를 넣어준다
	
	//1-1.의존성 주입
	@Resource(name = "boardService")//boardService라는 이름의 객체를 가져오겠습니다!
	private BoardService boardService;//스프링에서는 선언만!
	
	//게시글 목록 페이지 
	@GetMapping("/list")
	public String selectBoardList(Model model) {
		//1.게시글 목록 조회(한줄요약)
		model.addAttribute("boardList",boardService.selectBoardList());
		
		return "board/board_list";//어디로 이동할래?
	}
	
	//(양식)글등록하는 페이지로 이동: Form양식페이지로 안가는 이유가 있다!!
	///regBoard 컨트롤러로 넘어올 때 중복인데 어노테이션이 다르기때문 괜찮다!
	@GetMapping("/regBoard")//a태그,href일경우...
	public String regBoard() {
		return "board/reg_board";
	}
	
	//글 등록
	@PostMapping("/regBoard")//form태그로 넘어올땐!
	public String regBoard(BoardVO boardVO) {
		boardService.insertBoard(boardVO);
		return "board/reg_board_result";
	}
	
	//상세보기
	@GetMapping("/detail/{boardNum}")
	public String detailBoard(@PathVariable("boardNum") int boardNum,Model model) {
		model.addAttribute("boardList", boardService.selectDetailBoard(boardNum));
		
		return "board/detail_board";
	}
	
	//글수정 양식
	@GetMapping("/update/{boardNum}")
    public String update(@PathVariable("boardNum") int boardNum, Model model) {
//        model.addAttribute("boardList", boardService.updateBoard(boardNum));
        return "board/update_board";
    }
	//글수정
	@PutMapping("/update/{boardNum}")
	    public String update(BoardVO boardVO) {
//	        boardService.updateBoard(boardVO);
	        return "redirect:/";
	    }

	 //글 삭제
    @DeleteMapping("/delete/{boardNum}")
	    public String delete(@PathVariable("boardNum") int boardNum) {
	        boardService.deleteBoard(boardNum);

	        return "redirect:/";
	    }
	
}

 
  • BoardService
 package kh.study.board.service;

import java.util.List;

import kh.study.board.vo.BoardVO;

public interface BoardService {
	//게시글 목록조회
	List<BoardVO> selectBoardList();
	
	//글쓰기 등록
	void insertBoard(BoardVO boardVO);
	
	//상세보기
	BoardVO selectDetailBoard(int boardNum);
	//글 수정
	void updateBoard(BoardVO boardVO);
	//글 삭제
	void deleteBoard(int boardNum);
}
  • BoardServiceImpl
  package kh.study.board.service;

import java.util.List;

import org.mybatis.spring.SqlSessionTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import kh.study.board.vo.BoardVO;

@Service("boardService")//괄호안에 빈값이면 클래스명 소문자로 BoardServiceImpl 객체자동생성되기 때문에
public class BoardServiceImpl implements BoardService {
		   //쿼리 실행하는 객체
//		   SqlSessionFactory sqlSessionFactory = SqlSessionManager.getSqlSession();
//		   SqlSession sqlSession;//생성이 아닌 선언만
	
	//@Autowired어노테이션은 미리 생성한 객체를 의존성 주입 시킬 때 사용한다.
	//아래코드가 진행이 된다는 것은, 프로젝트 실행 시
	// 스프링이 내부적으로 sqlSessionTemplate 자료형으로 객체를 미리 만들어 놓기 때문에 사용가능하다.
	//@Autowired는 그래서 동일한 자료형으로 객체가 미리 2개 이상 생성되어있다면,
	//프로젝트 실행과 동시에 오류 발생
	//-> DB로 이동
	@Autowired//자동연결 (기준 자료형이 같은 객체만)
	SqlSessionTemplate sqlSession;

	
	//게시글 목록조회
	@Override
	public List<BoardVO> selectBoardList() {
		//원래 이클립스에서 하는 방식
//		List<BoardVO>  list = sqlSession.selectList("boardMapper.selectBoardList");
//		return list;
//		sqlSession.commit();(스프링은 자동 커밋)
		
		//->(스프링) 그래서 이제 부터 한 줄로 작성 가능해짐
		return sqlSession.selectList("boardMapper.selectBoardList");
	}
	
	//글쓰기 등록
	@Override
	public void insertBoard(BoardVO boardVO) {
		sqlSession.insert("boardMapper.insertBoard",boardVO);
	}
	//상세보기
	@Override
	public BoardVO selectDetailBoard(int boardNum) {
		return sqlSession.selectOne("boardMapper.selectDetailBoard",boardNum);
	}
	//글 수정
	@Override
	public void updateBoard(BoardVO boardVO) {
		sqlSession.update("boardMapper.updateBoard",boardVO);
		
	}
	//글 삭제
	@Override
	public void deleteBoard(int boardNum) {
		sqlSession.delete("boardMapper.insertBoard",boardNum);
		
	}
}
  • board-mapper
  <?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="boardMapper">
	<resultMap type="kh.study.board.vo.BoardVO" id="board">
		<id column="BOARD_NUM" property="boardNum"/>
		<result column="TITLE" property="title"/>
		<result column="WRITER" property="writer"/>
		<result column="CONTENT" property="content"/>
		<result column="CREATE_DATE" property="createDate"/>
	</resultMap>

<!-- 목록조회 -->
	<select id="selectBoardList" resultMap="board">
		SELECT BOARD_NUM 
		, TITLE
		, WRITER
		, CREATE_DATE
		FROM SPRING_BOARD
		ORDER BY BOARD_NUM DESC
	</select>
	
<!-- 게시글등록 -->	
	<insert id="insertBoard">
		INSERT INTO SPRING_BOARD (
			BOARD_NUM
			, TITLE
			, CONTENT
			, WRITER
		) VALUES(
			BOARD_NUM_SEQ.NEXTVAL
			, #{title}
			, #{content}
			, #{writer}
		) 
	</insert>
	
	<!-- 상세보기 -->
	<select id="selectDetailBoard" resultMap="board">
		SELECT BOARD_NUM
			, TITLE
			, WRITER
			, CONTENT
			, CREATE_DATE
		FROM SPRING_BOARD
		WHERE BOARD_NUM = #{boardNum}
	</select>
	
</mapper>

profile
Dev.Vinch

0개의 댓글