빅데이터 Java 개발자 교육 [Spring - 2 (DB연동 및 Controller,Mapper 작성방법)]

Jun_Gyu·2023년 5월 1일
0
post-thumbnail

먼저 오늘의 학습을 위해서 서버부터 가동시켜주도록 하자.

이후 board dto를 생성.

package com.example.dto;
import java.util.Date;
import lombok.Data;
import lombok.ToString;

@Data
@ToString(exclude = {"regdate"})

public class Board {
    private long no;
    private String title;
    private String content;
    private String writer;
    private long hit;
    private Date regdate;
}

게시글 작성 페이지 insert.html 작성

<!DOCTYPE html>
<html lang="ko">

<head>
    <meta charset='utf-8'>
    <meta http-equiv='X-UA-Compatible' content='IE=edge'>
    <meta name='viewport' content='width=device-width, initial-scale=1'>
    <title>게시글 작성</title>
    <link rel="stylesheet" th:href="@{/css/bootstrap.min.css}">
</head>

<body>
    <div>
        <h3>게시글 작성하기</h3>
        <hr />
        <form th:action="@{/board/insert.do}" method="post">
           제목 : <input type="text" name="title" value="test_title" /><br />
           내용 : <input type="text" name="content" value="test_content" /><br />
           작성자 : <input type="text" name="writer" value="test_writer" /><br />
            <input type="submit" value="글쓰기">
        </form>

    </div>
</body>

</html>

form 형태에서 action을 실행할 경로를 어제와 마찬가지로 th:~을 붙였다.

하지만 페이지에서 직접 소스를 확인해보면 기본 문법으로 변환되어 표시가 되는것을 확인할 수 있다.


작성한 위의 html을 실행시키면 다음과 같다.


이번에는 form태그를 Post형식으로 받아올 수 있도록 Controller에 PostMapping 작성하겠다.


jsp를 사용한 지난시간까지는 request를 통해 받아오려는 객체의 명칭을 하나하나 지정해주었으나, Spring을 사용하는 지금은 좀더 간편한 방법을 사용하고자 한다.

(한눈에 봐도 코드가 간결하다.)

받아오려는 form 태그의 모든 데이터를 dto형식에 담아서 곧바로 DB로 보내는 형식이다.

jsp에서는 하나하나 받아온 데이터들을 controller 내부에서 dto에 값을 담아 DB로 전송하는 방식이었다면,

이제부터는 불필요한 중간과정을 줄이고 처음부터 DTO로 받아오는 형식인것이다.

(대신 안되는 부분은 하나하나 받아와야지..)

아래는 방금 그 코드이다.

 // 게시글 입력
    @PostMapping(value = "/insert.do")
    public String insertPost( @ModelAttribute Board board ) {
        System.out.println(board.toString());

        // DB에 추가
        
        // 적절한 페이지로 이동
        return "redirect:select.do";
    }

이를 실행하기 위해서는 dto에 있는 객체명과 html로부터 controller로 받아오려는 name이 일치해야 한다.



(서로 같아야 함!)


DB경로 설정 (Mybatis)

DB에 연동을 하기 위해서 아래의 두가지 dependency들을 추가했다.

<!-- h2, oracle, mysql -->
	<dependency>
		<groupId>com.h2database</groupId>
		<artifactId>h2</artifactId>
	</dependency>

<!-- mybatis -->
	<dependency>
		<groupId>org.mybatis.spring.boot</groupId>
		<artifactId>mybatis-spring-boot-starter</artifactId>
		<version>3.0.0</version> 
	</dependency>

그리고 Mybatis를 설정해주도록 하자.

기존의 mybatis인 경우에는 클래스를 생성하여 연결할 DB의 정보들을 담아 주었지만,

Spring을 사용할때는 application.properties 환경설정을 사용하여 세부 내용들을 설정해준다.

그렇다면 이번엔 Service 및 Impl을 한번 설계해보도록 하겠다.

Service 및 Impl 추가

기존에는 빠른 이해와 간단한 코딩을 위해서 Controller에서 곧바로 Mapper를 연결했었지만, 실제로는 위와 같은 방법으로 코딩을 하면 안된다.

먼저 Controller에서 Service로 데이터를 보낸 뒤, Service에서 받은 내용을 Impl에서 처리하고 DB로 보내는 식으로 진행되어야 하는 것이다.

아래는 Service와 Impl을 구성한 내용이다.

BoardService

package com.example.service;

import java.util.List;

import org.apache.ibatis.annotations.Param;
import org.springframework.stereotype.Service;

import com.example.dto.Board;


@Service
// Shift + alt + o = [자동으로 import]!
public interface BoardService {
    // 게시글 등록
    public int insertBoardOne(@Param("obj") Board obj);

    // 게시글 전체조회
    public List<Board> selectBoardList();

}

BoardServiceImpl (@Autowired)

package com.example.service;

import java.util.List;

import org.springframework.stereotype.Service;

import com.example.dto.Board;
import com.example.mapper.BoardMapper;

import lombok.RequiredArgsConstructor;

@Service
@RequiredArgsConstructor // 클래스에서만 가능함, 인터페이스에서는 안됨
public class BoardServiceImpl implements BoardService {
    // @Autowired를 통해서 직접 Mapper를 지정해줌!
    /* 반드시 붙어있어야 함! */
    final BoardMapper bMapper; // @Autowired BoardMapper bMapper;
    /* /반드시 붙어있어야 함! */

    @Override
    public int insertBoardOne(Board obj) {
        try {
            return bMapper.insertBoard(obj);
        } catch (Exception e) {
            throw new UnsupportedOperationException("Unimplemented method 'insertBoardOne'");
        }
    }

    @Override
    public List<Board> selectBoardList() {
        try {
            return bMapper.selectBoard();
        } catch (Exception e) {
            e.printStackTrace();
            return null;
        }
    }
}

위의 코드를 자세히 보면

// @Autowired를 통해서 직접 Mapper를 지정해줌!
    /* 반드시 붙어있어야 함! */
    final BoardMapper bMapper; // @Autowired BoardMapper bMapper;
    /* /반드시 붙어있어야 함! */

라는 부분이 있는것을 확인할 수 있는데,

이는 기존에 생성해두었던 Mapper와 연결하여 기능을 최적화한다는 이야기이다.
간단하게 @Autowired BoardMapper bMapper; 로 사용 할 수도 있고,

@RequiredArgsConstructor //어노테이션을 추가한 후

final BoardMapper bMapper;

와 같은 형태로도 사용할 수 있다.



꿀팁!


Ctrl + 좌클릭 한 후 Add unimplemented methods 누르면 자동으로 필요한 메소드 생성!

BoardMapper

package com.example.mapper;

import java.util.List;

import org.apache.ibatis.annotations.Insert;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Param;
import org.apache.ibatis.annotations.Select;

import com.example.dto.Board;

@Mapper
public interface BoardMapper {
   // 글쓰기
   @Insert(value = {
           "	INSERT INTO board( title, content, writer)	",
           "	VALUES( #{obj.title}, #{obj.content}, #{obj.writer}  )	"
   })
   public int insertBoard(@Param("obj") Board board);

   // 전체목록
   @Select(value = {
           "	SELECT * FROM board	ORDER BY no DESC	"
   })
   public List<Board> selectBoard();
}

위와 같이 mapper, Service, Impl을 모두 연결했지만, 아마도 오류때문에 실행이 되지 않을것이다. 그 이유는,

프로젝트 파일에서 기존에 Controller의 위치는 설정해주었지만, Mapper와 Service의 위치를 설정해주지 않았기 때문에 그런 것이다.

// 매퍼 위치 설정
@MapperScan(basePackages={"com.example.mapper"})
 // 컨트롤러, 서비스 위치 설정 (이중으로 가능)
@ComponentScan(basePackages={"com.example.controller", "com.example.service"})

따라서 프로젝트 파일인FirstSpringStudyApplication.java 에서 매퍼, 그리고 Service의 위치설정이 필요하다고 볼 수 있다.

xml 형태의 Mapper 구성하기

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.example.mapper.BoardMapper"> 
<!-- 기존의 interface BoardMapper명과 일치해야 함-->
    <update id="updateBoardOne" parameterType="com.example.dto.Board">
        UPDATE BOARD SET title=#{title}, content=#{content}, writer=#{writer} WHERE no=#{no}
    </update>

    <delete id="deleteBoardOne" parameterType="long">
        DELETE FROM BOARD WHERE no=#{no}
    </delete>
</mapper>

기존에는 class에서 Mapper의 기능을 수행하였다. 하지만 최근에는 위와 같이 xml파일의 형태로 Mapper를 구성하는 방법또한 사용하고 있으니 알아두도록 하자.

대신 기존에 사용하고 있었던 Mapper가 있다면, 명칭을 똑같이 통일해주어야 정상적인 사용이 가능하겠다.

Mapper 위치 환경설정 (applcation.properties)

# sql문이 있는 위치 설정(mybatis)
mybatis.mapper-locations=classpath:/mappers/*Mapper.xml

Mapper의 새로운 경로를 환경설정으로 추가해주자.

profile
시작은 미약하지만, 그 끝은 창대하리라

0개의 댓글