16日目

55779 ワード

韓日

  • DB接続(+テストクエリー)
  • サービスパック
  • コントローラクラス
  • 登録
  • 投稿
  • 掲示板の作成


    MyBatisを使用した掲示板の作成

    データベース接続



    テーブルのデータをインポートするクラスBoardVOの作成
    - BoardVO -
    @Data
    public class BoardVO {
    	
    	private int bno;		// 게시글 번호
    	private String title;	// 제목
    	private String content;	// 내용
    	private String writer;	// 글쓴이
    	private LocalDateTime regdate;	// 등록날짜 timestemp에서 날짜시간을 가져오는 자바 날짜시간데이터
    	private LocalDateTime updateDate;	// 수정날짜
    }
    @Data:@Getter@Setter@ToString統計機能

    BoardMapperインタフェースを作成します(daoと同じなので混合して使用できます)
    - BoardMapper -
    @Mapper
    public interface BoardMapper {
    	public void enroll(BoardVO board);	// 게시판 등록
    }
    新しい投稿登録機能を宣言します.(実装は、異なるクラスでインタフェースを実装する必要があります.)
    機能を実装する前にインタフェースを作成します.
    - application.properties -
    # MyBatis
    # mapper.xml
    mybatis.mapper-locations: mapper/*.xml
    
    # model 열이름 언더바 '_' -> camel case setting
    mybatis.configuration.map-underscore-to-camel-case=true
    
    # 패키지 result type의 패키지를 생략할 수 있도록 model packge 위치 지정
    mybatis.type-aliases-package=com.myapp.bbs.model
    
    # mapper log level setting
    logging.level.com.myapp.mybatis.mapper=TRACE
    - BoardMapper.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.myapp.bbs.dao.BoardMapper">
    
    	<select id="enroll" resultType="BoardVO">
    		INSERT INTO board (title, content, writer)
            VALUES (#{title}, #{content}, #{writer})
    	</select>
    </mapper>
    JavaソースのBoardMapperパスを<mapper>タグに適用する必要があります.
    BoardMapperインタフェースの実装.xmlで行います.idインタフェースで指定されたメソッドの名前(登録)を入力し、resultTypeで返されるオブジェクト(BoardVO)を入力します.

    クエリ文のテスト


    jpaとは異なり、独自に作成されているので、テストツールを使用して検証します.
    - pom.xml -
    <!-- 마이바티스 테스트 -->
    <dependency>
    	<groupId>org.mybatis.spring.boot</groupId>
    	<artifactId>mybatis-spring-boot-starter-test</artifactId>
    	<version>2.2.2</version>
    	<scope>test</scope>
    </dependency>
    dependenciesの下部に追加します.テストツールで使用するライブラリを追加します.

    テスト用のBoardMapperTestクラスを作成します.(*インタフェースではなくクラスとして作成)
    - BoardMapperTest -
    @MybatisTest
    @AutoConfigureTestDatabase(replace = Replace.NONE)	// 현재 연결된 실제DB로 테스트함을 의미
    @Rollback(value = false)							// 테스트시 롤백 안함
    public class BoardMapperTests {
    	// Junit 5버전으로 테스트
    	@Autowired
    	private BoardMapper boardMapper;
    	
    	@Test
    	public void testEnroll() {
    		BoardVO vo = new BoardVO();
    		
    		vo.setTitle("test Title");
    		vo.setContent("test Content");
    		vo.setWriter("test Writer");
    		
    		boardMapper.enroll(vo);
    	}
    }
    @AutoConfigureTestDatabase(replace = Replace.NONE)は、現在接続されている実際のDBを用いてテストを行うことを示す@Rollback(value = false)テストを実行した後、データはロールバックされません.データをロールバックするのは難しいので、入力テストが正しく完了したことを確認します.


    testEnrollメソッドを実行します.

    テストが正常に完了すると、データベースのboardテーブルに新しく入力したデータが表示されます.
    テストが設定されると、他の方法をテストするときに使用できます.

    サービスパック


    コントローラに直接適用するのではなく、サービス層を作成します.
    - BoardService.interface -
    public interface BoardService {
    	
    	public void enroll(BoardVO board);	// 게시글 등록
    }
    BoardServiceImplクラスを作成してサービスインタフェースを実装
    - BoardServiceImpl -
    @Service
    public class BoardServiceImpl implements BoardService {
    	
    	private BoardMapper boardMapper;
    	
    	// 생성자 주입
    	public BoardServiceImpl(BoardMapper boardMapper) {
    		this.boardMapper = boardMapper;
    	}
    	
    	@Override
    	public void enroll(BoardVO board) {
    		boardMapper.enroll(board);
    	}
    }
    クラスに@Serviceアクションが作成されている場合にのみ、スプリングが認識されます.
    作成者が注入されたため、BoardServiceImplオブジェクトを作成するとBoard Mapperオブジェクトも自動的に注入されます.
    ここではregirlメソッドが実際に実行する必要がある機能を上書きすることによって再定義する.boardMapper.enroll(board)は、受信したボードオブジェクトをパラメータとしてデータベースに入力する機能である.

    コントローラクラス


    - BoardController -
    @Controller
    @RequestMapping("/board")
    @Log		// 콘솔에 로그 출력 (print out 대신 로그출력)
    public class BoardController {
    	@GetMapping("/list")
    	public String boardListGet() {
    		log.info("게시판 리스트 페이지 진입");
    		return "list";
    	}
    	@GetMapping("/enroll")
    	public String boardEnrollGet() {
    		log.info("게시판 등록 페이지 진입");
    		return "enroll";
    	}
    }
    @Logログで簡単に結果を表示
    http://localhost:8080/board/list

    viewが作成されていないためエラーが発生しましたが、ログ内の文は正常にアクセスできることを確認します.

    viewの作成


    - list.html -
    <!DOCTYPE html>
    <html xmlns:th="http://www.thymeleaf.org">
      <head>
        <meta charset="UTF-8" />
        <meta http-equiv="X-UA-Compatible" content="IE=edge" />
        <meta name="viewport" content="width=device-width, initial-scale=1.0" />
        <title>게시판 리스트</title>
      </head>
      <body>
        <h1>목록 페이지</h1>
        <a th:href="@{/board/enroll}">게시글 등록</a>
      </body>
    </html>
    投稿リストを表示するリスト.htmlの生成
    - enroll.html -
    <!DOCTYPE html>
    <html xmlns:th="http://www.thymeleaf.org">
      <head>
        <meta charset="UTF-8" />
        <meta http-equiv="X-UA-Compatible" content="IE=edge" />
        <meta name="viewport" content="width=device-width, initial-scale=1.0" />
        <title>게시글 등록</title>
      </head>
      <body>
        <h1>등록 페이지</h1>
      </body>
    </html>
    http://localhost:8080/board/list

    リストページに戻ると、ビューが正常に出力されます.

    各ページに入るたびに、ログに表示されます.
    sysoutよりもチェックしやすいです.

    ビューにテンプレートを適用



    テンプレートコピー貼り付け気候HomeConrollerの作成と検証
    - HomeController -
    @Controller
    public class HomeController {
    
    	@GetMapping(value = {"/", "dashboard"})
    	public String dashBoard() {
    		return "pages/dashboard";
    	}
    	
    	@GetMapping("/tables")
    	public String showTable() {
    		return "pages/tables";
    	}
    	
    	@GetMapping("/profile")
    	public String showProfile() {
    		return "pages/profile";
    	}
    	
    	@GetMapping("/sign-in")
    	public String login() {
    		return "pages/sign-in";
    	}
    	
    	@GetMapping("/sign-up")
    	public String register() {
    		return "pages/sign-up";
    	}	
    }
    http://localhost:8080/
    ホームアドレス確認へ
    enroll.htmlの変更
    - enroll.html -
    <div class="card-header">
      <h4 class="font-weight-bolder">새 게시글 작성</h4>
      <p class="mb-0">새로운 게시글을 작성하세요</p>
    </div>
    <div class="card-body bg-white">
      <form role="form" th:action="@{/board/enroll}" method="post" th:object="${board}">
        <div class="input-group input-group-outline mb-3">
          <label class="form-label">제목</label>
          <input type="text" class="form-control" th:field="*{title}" required />
        </div>
        <div class="input-group input-group-outline mb-3">
          <div class="input-group input-group-dynamic">
            <textarea th:field="*{content}" class="form-control" rows="5" placeholder="내용을 적어주세요." spellcheck="false" required></textarea>
          </div>
        </div>
        <div class="input-group input-group-outline mb-3">
          <label class="form-label">글쓴이</label>
          <input type="text" class="form-control" th:field="*{writer}" required />
        </div>
        <div class="text-center">
          <button type="submit" class="btn btn-lg bg-gradient-primary btn-lg w-100 mt-4 mb-0">게시하기</button>
        </div>
      </form>
    </div>

    投稿の登録


    - BoardController -
    @GetMapping("/enroll")
    public String boardEnrollGet(Model model) {
    	
    	model.addAttribute("board", new BoardVO());
    	return "enroll";
    }
    Board EnrollGetメソッドを変更します.
    モデルをパラメータとして使用して、フォームのデータを使用可能にし、BoardVOにパブリッシュするオブジェクトのデータを入力します.
    http://localhost:8080/board/enroll

    - BoardController -
    @PostMapping("/enroll")
    public String boardEnrollPost(BoardVO board) {
    	log.info("Board : "+ board);
    	return "redirect:/board/enroll";
    }
    コントローラに「書く」ボタンをクリックしたときにpostに送信する方法を追加します.
    「リダイレクト/ボード/登録」ページにリダイレクト
    http://localhost:8080/board/enrollにテスト内容を記入し、「発行」ボタンを押して提出します.2022-04-15 11:28:07.692 INFO 11764 --- [nio-8080-exec-3] c.myapp.bbs.controller.BoardController : BoardVO : BoardVO(bno=0, title=제목1, content=내용, writer=홍길동, regdate=null, updateDate=null) 文がコンソールに表示されていることを確認できます.
    テスト終了後、入力DBの機能を記述する番になりました.
    - BoardController -
    private BoardService boardService;
    
    public BoardController(BoardService boardService) {
    	this.boardService = boardService;
    }
    	// ...생략...
    @PostMapping("/enroll")
    public String boardEnrollPost(BoardVO board) {
    //		log.info("BoardVO : "+ board); 테스트 완료
    	boardService.enroll(board);
    	return "redirect:/board/enroll";	// post - redirect
    }

    nav.htmlの変更
    <nav aria-label="breadcrumb">
      <h6 id="pageName" class="font-weight-bolder mb-0 py-3">페이지 제목</h6>
      <script th:if="${message}">
        let m = '[[${message}]]'; // 리다이렉트로 넘어온 메시지 저장
        alert(m); // 화면에 메시지 띄우기
      </script>
    </nav>
    [[${message}]]:JavaScriptリダイレクト${message}を使用
    - BoardController -
    @PostMapping("/enroll")
    public String boardEnrollPOST(BoardVO board, RedirectAttributes attr) {
    	//log.info("BoardVO : " + board);
    	boardService.enroll(board);
    	attr.addFlashAttribute("message", "게시글 등록 성공!");
    	return "redirect:/board/list";
    }
    list.html
    <body class="g-sidenav-show bg-gray-200">
      <aside th:replace="fragments/aside :: 어사이드"></aside>
      <!-- 메인 컨텐트 시작 -->
      <main class="main-content position-relative max-height-vh-100 h-100 border-radius-lg">
        <!-- 상단 네브바 -->
        <nav th:replace="fragments/nav :: 네브"></nav>
        <!-- 컨텐츠 시작 -->
        <div class="container-fluid py-4">
          <!-- 빈 컨텐츠 (여기서 시작)-->
          <h1>게시글 리스트 페이지</h1>
        </div>
      </main>
    
      <!-- 오른쪽 숨김창 , JS 링크들 -->
      <hidden th:replace="fragments/hidden :: 숨김창"></hidden>
      <jslink th:replace="fragments/jslink :: 링크"></jslink>
      <script>
        document.getElementById('pageName').textContent = '게시판 목록';
      </script>
    </body>

    作成後に[パブリッシュ](Publish)をクリック

    「投稿リスト」ページに移動し、

    [OK]をクリックして[投稿リスト]ページに移動したことを確認します

    DBのboardテーブルにも格納されます.