Spring/Spring Boot

[SpringBoot] 3. 게시판으로 CRUD 기능 구현 - (1)

칸쵸. 2023. 11. 28. 02:32
728x90

 

안녕하세요

오늘로 세 숟가락 째 뜨게되는 글이군요

 

아직 배는 부르지 않지만, 알듯말듯 아리송 할 정도는 온 것같아요.

 

알리송 ㅋㅋ

 

알듯말듯 아리송 알리송 ㅋㅋ

역시 새벽 블로그는 제정신이 아닌 맛이죠 레지고

 

아 참!

그리고 여전히 틀린 정보 속출 가능합니다.

 


 

네 오늘은~ 본격적인 프로젝트 생성에 앞서

 

Oracle DB에 'BOARD'라는 테이블을 먼저 생성하는 사전 작업이 필요합니다.

까짓거 만들면 되죠 뭐.

 

 

CREATE TABLE Board (
    board_id NUMBER(10) PRIMARY KEY,
    title VARCHAR2(100),
    content VARCHAR2(200), 
    author VARCHAR2(50)
);

 

이렇게 생긴놈을 하나 만들어주면 됩니다.

그리고 PK로 지정한 board_id 번호는 사용자 직접 지정이 아닌, 게시글 작성을 하면 자동으로 값이 부여되도록 시퀀스랑 트리거도 하나씩 만들어서 적용해주겠어요. 급귀찮...

 

자세한 설명은 생략하겠습니다.. 암튼 다들 알아서 잘 했을거라 믿어요

SQL 원투데이 한거 아니잖아요?

 

--1부터 시작해서 1씩 증가하는 sequence 생성
CREATE SEQUENCE board_seq
  START WITH 1
  INCREMENT BY 1
  NOCACHE
  NOCYCLE;

--board에 값이 들어올 때마다 board_id 값이 증가하는 trigger 생성
CREATE OR REPLACE TRIGGER board_trigger
BEFORE INSERT ON board
FOR EACH ROW
BEGIN
    SELECT board_seq.NEXTVAL
    INTO:NEW.board_id
    FROM dual;
END;
/

 

 

 

사전작업 말하는 김에 프로젝트도 그냥 여기서 만들게용

 

저는 Spring-Board라는 이름의 Spring Starter 프로젝트를 만들겠습니다.

Type : Maven이랑 Dependency 6개 추가해줬어요

 

 

그럼 이제 진짜 끝~


 

< application.properties >

 

## DB 연결 설정
spring.datasource.url = jdbc:oracle:thin:@//localhost:1521/XE
spring.datasource.username = [사용자이름]
spring.datasource.password = [사용자비밀번호]
spring.datasource.driver-class-name = oracle.jdbc.OracleDriver

 

그리고 일단 쓰래서 쓰는 이 친구

 

 

무슨 뜻인지 갑자기 궁금해져서 찾아봤더니... (참 빨리도 궁금한 사람)

 

mybatis.mapper-location = classpath:/mapper/*.xml

mapper 폴더 아래에 존재하는 모든 xml 파일을 mapper로 인식

 

mybatis.type-aliases-package

xml 파일 result type에 패키지명 생략할 수 있도록 alias 설정 (VO 파일 경로)

 

그럼 이걸 또 왜 쓰는건가 했는데, 생각해보니 Mapper.java와는 다르게 model이나 mapper.xml 파일같은 경우에는 '얘가 뭐다~'하고 알려주는 어노테이션도 딱히 없어서 그 설정을 따로 해주는 개념이라고 보면 될 것같다.

 

암튼 다음 단계

 


 

< BoardMapper.xml >

 

이전과 동일하게 resource 폴더 아래에 mapper 폴더 생성 후 파일을 넣어줬다.

이젠 이유를 알아요~

왜? mybatis.mapper-location방금 그렇게 정했으니까~

 

그리고 이번에는 기능 구현을 크게 총 4가지로 잡았다

 

  1. 전체 게시물 목록 조회
  2. board_id를 통해 특정 게시물 1개 조회 (게시물 상세보기)
  3. 게시글 작성
  4. 게시글 수정
  5. 게시글 삭제

 

얼라리. 쓰고보니 5개네요 죄송 ㅎㅎ 암튼 그에 맞춰 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.springdb.mapper.BoardMapper">
	
	<!-- resultMap으로 다 가지고 오기 -->
	<resultMap id="BoardResultMap" type="com.example.springdb.model.Board">
		<id property="board_id" column="board_id"/>
		<result property="title" column="title"/>
		<result property="content" column="content"/>
		<result property="author" column="author"/>
	</resultMap>
	
	
	<!-- 전체 게시판 내용 조회하는 어쩌구 --><!-- resultType 아니고 resultMap임 주의 (두 개 동시 사용 불가)-->
	<select id="getAllBoards" resultMap="BoardResultMap">
		SELECT * FROM board
	</select>
	
	<!-- 게시물 1개 상세보기 -->
	<select id="getBoardById" parameterType="int" resultMap="BoardResultMap">
		SELECT * FROM board WHERE board_id = #{board_id}
	</select>
	
	<!-- 게시글 쓰기 -->
	<insert id="insertBoard" parameterType="com.example.springdb.model.Board">
		INSERT INTO board(board_id, title, content, author)
		VALUES(#{board_id}, #{title}, #{content}, #{author})
	</insert>
	
	<!-- 게시글 수정 -->
	<update id="updateBoard" parameterType="com.example.springdb.model.Board">
		UPDATE board 
		SET title= #{title}, content=#{content}, author=#{author}
		WHERE board_id = #{board_id}
	</update>
	
	<!-- 게시글 삭제 -->
	<delete id="deleteBoard" parameterType="int">
		DELETE FROM board
		WHERE board_id = #{board_id}
	</delete>
	
</mapper>

 

이 놈의 태그. 무슨 놈의 종류가 이렇게 많은지 용어도 하나도 모르겠다.. 하면서 친 것같은데

그래도 좀 눈에 익고있는게 웃기다

 

나름대로 정리.. 고퀄은 기대하지 마시라

 

1. xml문서 및 DTD(태그 규칙) 선언

 

2. <mapper>

 

<mapper> 태그는 root element라고도 불리며, mapper 파일에 작성하는 모든 SQL문은 <mapper> 태그에 묶인다

그리고 namespace 속성에는 뒤에 생성할 mapper 인터페이스 명을 적어준다

이제 당신은 꼼짝없이 BoardMapper라는 인터페이스를 생성해야한다

 

암튼 그럼 이제 <mapper>태그에 묶인 SQL 구문들이 뒤에 생성될 인터페이스로 호출될 예정.

 

3. <select>, <insert>, <update>, <delete>

 

SQL 명령어에 따라서 SELECT문은 <select>, INSERT문은 <insert>...와 같은 모양새로 태그를 만들어서 그 밑에 SQL 구문을 작성해준다

 

예시

 

그럼 또 id는 뭐고 resultMap은 뭔지 궁금해진다...

일단 id는 각 SQL구문을 구분하기 위한 녀석으로 알면되겠고

 

4. resultMap

 

resultMap이랑 전에 사용한 resultType에 대한 설명은 mybatis 홈페이지에 들어가면 확인 가능하다

https://mybatis.org/mybatis-3/sqlmap-xml.html

 

진짜 쉽게 말하자면 resultType은 쿼리 실행 결과값을 객체 통째로 받는거고,

resultMap은 사용자가 원하는 컬럼만 뽑아서 쿼리 실행 결과값을 받아올 수 있게 된다.

그래서 resultMap이 좀 더 쓰기 귀찮기는 하지만, 입맛대로 쓰기에는 좋다.

 

**주의 : resultMap 혹은 resultType 동시 사용 불가

 

5. parameterType

 

게시물 상세보기같은 경우, board_id라는 값을 통해 상세정보를 조회할 예정이다.

당연히 int형 매개변수가 필요해서 저렇게 써줬다 (게시글 삭제의 경우도 마찬가지)

 

나머지는 설명 패스

 


 

< BoardMapper.java >

 

아까 mapper.xml 파일에서 선언한 BoardMapper 인터페이스를 작성한 경로에 맞춰서 생성해준다.

mapper 인터페이스는 결국, 매핑파일(mapper.xml)에 기재된 SQL을 호출하기 위한 공간인 셈

 

그리고 각 SQL문을 담은 id값에 맞춰서 메서드도 생성해준다.

아니 그런데 쓰다보니까 갑자기 뭔가 이상한 것을 깨달았다. Model을 안만들어줬네 내가;;

 

board 테이블에 존재하는 컬럼명 및 데이터 타입에 맞춰서 파일하나 만들어주고 올게요..

com.example.springdb.model 패키지에 Board.java 생성 완료 (멤버변수 & GetterSetter)

 

순서가 이러면 완전 엉터리입니다 여러분들은 이러지 마세요

아무튼 그렇게 작성한 BoardMapper

 

package com.example.springdb.mapper;

import java.util.List;

import org.apache.ibatis.annotations.Mapper;

import com.example.springdb.model.Board;

@Mapper
public interface BoardMapper {

	//전체 게시글 조회
	List<Board> getAllBoards();
	
	//게시글 상세보기 by board_id
	Board getBoardById(int board_id);
	
	//게시글 작성
	void insertBoard(Board board);
	
	//게시글 수정
	void updateBoard(Board board);
	
	//게시글 삭제
	void deleteBoard(int board_id);
}

 

 


 

< BoardController.java >

 

이거 이제서야 파일을 만들다가 느낀건데, 작업순서가 어쩌구해서 너무 정석으로 따르니까 정신도 없고 난감할 때가 많다;;

처음에는 내용 작성은 나중에 하더라도, 프로젝트에 필요한 클래스는 알맞은 경로에 다 생성이라도 해놓고 작업해야지 안되겠다.. 아무튼

 

동일하게 com.example.springdb.controller 패키지에 BoardController.java 생성

 


 

분량조절 실패로 2부로 돌아오겠습니다

 

 

 

20231129 기준 : 2부 완성!

 

[SpringBoot] 3. 게시판으로 CRUD 기능 구현 - (2)

이 글은 '게시판으로 CRUD 기능 구현 -(1)'과 이어집니다. [SpringBoot] 3. 게시판으로 CRUD 기능 구현 - (1) 안녕하세요 오늘로 세 숟가락 째 뜨게되는 글이군요 아직 배는 부르지 않지만, 알듯말듯 아리

im2ho.tistory.com