Spring 강의 day 2

주세환·2023년 4월 28일
0

Spring

목록 보기
2/18

Board 생성

java/com/example에 dto 폴더를 생성하여 Board.java를 생성한다.

package com.example.dto;

import java.util.Date;

import lombok.AllArgsConstructor;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter;
import lombok.ToString;

@Getter
@Setter
@ToString(exclude = {"regdate"})
@NoArgsConstructor
@AllArgsConstructor
public class Board {
    private long no;
    private String title;
    private String content;
    private String writer;
    private long hit;
    private Date regdate;

}

Board.java


<!DOCTYPE html>
<html lang="en">
<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>
    <div>
        <h3>게시판 글쓰기</h3>
        <hr />

    </div>
</body>
</html>

insert.html을 생성한다.

<body>
    홈화면
    <p th:text="${title}"></p>
    <div th:text="${abc}"></div>
    
    <a th:href="@{/board/insert.do}">게시판 글쓰기</a>
</body>

home.html에 위 코드를 추가하면

게시판 글쓰기로 이동하는 링크가 추가된다.


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

insert.html을 수정한다.

게시판 글쓰기를 누르면

이렇게 작성한대로 추가된다.

주소가 사진처럼 바뀌는 모습을 볼 수 있다.


<form th:action="@{/board/insert.do}" method="post">
    제목 : <input type ="text" name="title" value="1" /><br />
    내용 : <input type ="text" name="content" value="2" /><br />
    작성자 : <input type ="text" name="writer" value="3" /><br />
    <input type ="submit" value="글쓰기" />
</form>

insert.html을 위처럼 수정한다.

이렇게 값이 추가된다.

글쓰기 버튼을 누르면

이런 오류가 뜬다.

POST로 받는 곳이 없기 때문이다.

POST를 만들어보자


Post

public class BoardController {

    // 게시판 글쓰기
    @PostMapping(value ="/insert.do")
    public String insertPost(
        @RequestParam(name = "title") String title, 
        @RequestParam(name = "content") String content, 
        @RequestParam(name = "writer") String writer ) {
        // 넘어온 값 확인
        System.out.println(title);
        System.out.println(content);
        System.out.println(writer);

        // DB에 추가

        // 적절한 페이지로 이동(게시판 목록으로)
        return "redirect:select.do";
    }   

BoardController를 위처럼 수정한다.

글쓰기 버튼을 누르면

return에 입력한 주소값인 select.do로 이동하게 된다.


값 불러오기

// 게시판 글쓰기
@PostMapping(value ="/insert.do")
public String insertPost(
    @RequestParam(name = "title") String title, 
    @RequestParam(name = "content") String content, 
    @RequestParam(name = "writer") String writer ) {
    Board obj = new Board();
    obj.setTitle(title);

java를 사용할 땐 이렇게 객체를 만들어서 obj.setTitle(title); 이런 식으로 정보를 받아왔지만

// 게시판 글쓰기
@PostMapping(value ="/insert.do")
public String insertPost( @ModelAttribute Board board){
    System.out.println(board.toString());
    
    // DB에 추가

    // 적절한 페이지로 이동(게시판 목록으로)
    return "redirect:select.do";
} 

Spring은 이렇게 @ModelAttribute 를 이용하여 dto파일로 바로 정보를 받아올 수 있다.

맨 아래쪽에 Board의 정보를 받아온 모습을 볼 수 있다.

dto에 작성한 이름과 html의 name값이 같아야만 불러올 수 있다.


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>

pom.xml에 dependency를 추가한다.

DB 연동

# db 연동
spring.datasource.driver-class-name=org.h2.Driver
spring.datasource.url=jdbc:h2:tcp://1.234.5.158:31521/ds201;Mode=Oracle
spring.datasource.username=sa
spring.datasource.password=

application.properties에 위 코드를 추가한다.

늘 사용하던 h2 주소이다.

application.properties 코드 뒤에 공백(스페이스바)가 있으면 안되니 꼭 주의하자.

Service

insertBoardOne

service 폴더에 BoardService.java를 생성한다.

package com.example.service;

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

import com.example.dto.Board;

// shift + alt + o : 자동 임포트
@Service
public interface BoardService {
    // 게시글 등록
    public int insertBoardOne(@Param("obj") Board obj);
}

BoardService.java

이어서 BoardServiceImpl도 생성한다.


빨간줄이 생기는 BoardServiceImpl을 누르면 왼쪽에 노란색 전구 아이콘을 눌러
Add unimplemented methods를 선택한다.

@Service
public class BoardServiceImpl implements BoardService {

    @Override
    public int insertBoardOne(Board obj) {
        try{

        }
        catch(Exception e){
        throw new UnsupportedOperationException("Unimplemented method 'insertBoardOne'");
        }
    }
}

BoardServiceImpl이다.

이제 Mapper를 생성하자.


src - main - java - com - example에 mapper 폴더를 생성하여 그 안에 BoardMapper.java를 만든다.

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

BoardMapper.java


@Service
public class BoardServiceImpl implements BoardService {

    @Autowired
    BoardMapper bMapper;

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

BoardServiceImpl을 위처럼 수정한다.

@Autowired는 자동으로 객체를 생성해주는 기능이다.
뒤에 객체명인 BoardMapper bMapper;까지 꼭 작성해야 한다.


@RequestMapping(value="/board")
public class BoardController {

    @Autowired BoardService bService;

// 게시판 글쓰기
@PostMapping(value ="/insert.do")
public String insertPost( @ModelAttribute Board board){
    System.out.println(board.toString());
        
        int ret = bService.insertBoardOne(board);
        if(ret == 1){ // 성공시
            // 적절한 페이지로 이동(게시판 목록으로)
            // return "redirect://member/select.do";
            return "redirect:select.do";
        }
        // 실패시
        return "redirect:insert.do";
    }   

BoardController.java를 위처럼 수정한다.

@Autowired 또한 추가한다.


// 새로운 패키지를 생성하고 역할을 부여하면 반드시 실행파일에 등록해야 함.

@SpringBootApplication
@MapperScan(basePackages = {"com.example.mapper"}) // mapper 위치
@ComponentScan(basePackages = {"com.example.controller", "com.example.service"}) // 컨트롤러, 서비스 위치 설정

Boot20230427Application.java에 위 코드를 추가한다.


@Controller
@RequestMapping(value="/board")
@RequiredArgsConstructor // 클래스에서만 가능함, 인터페이스에서는 안됨.
public class BoardController {

    final BoardService bService;
    // @Autowired BoardService bService;

BoardController를 위처럼 수정한다.


selectBoardList

// 전체조회
@Select({
    " SELECT b.* FROM board b ORDER BY no DESC "
})
public List<Board> selectBoardList();

mapper를 추가한다.

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

BoardService에도 추가하고

@Service
@RequiredArgsConstructor
public class BoardServiceImpl implements BoardService {

    final BoardMapper bMapper; // @Autowired BoardMapper bMapper;와 같음
    
    ...
    
@Override
public List<Board> selectBoardList() {
    try{
        return bMapper.selectBoardList();
    }
    catch(Exception e){
        e.printStackTrace();
        return null;
    }
}    

BoardServiceImpl에도 추가한다.

// 127.0.0.1:9090/ROOT/board/select.do
@GetMapping(value="/select.do")
public String selectGET(Model model){
    List<Board> list = bService.selectBoardList();
    model.addAttribute("list", list);
    
    // templates에서 board폴더를 생성하고 select.html생성
    return "/board/select";
}

BoardController.java에 추가로 작성한다.


<body>
    <h3>게시글목록</h3>
    <a th:href="@{/board/insert.do}">글쓰기</a>
    <table>
        <thead>
            <tr>
                <th>번호</th>
                <th>제목</th>
                <th>작성자</th>
                <th>조회수</th>
                <th>날짜</th>
            </tr>
        </thead>
        <tbody>
            <tr th:each="one : ${list}">
                <td th:text="${one.no}"></td>
                <td th:text="${one.title}"></td>
                <td th:text="${one.writer}"></td>
                <td th:text="${one.hit}"></td>
                <td th:text="${one.regdate}"></td>
            </tr>
        </tbody>
    </table>
</body>
</html>

select.html도 추가하여 서버에 연결해보자.

글쓰기를 누르면

1 2 3이 추가로 등록되고 DB에 저장되어있는 정보들이 나온다.


selectone

@GetMapping(value = {"/selectone.do"})
public String selectoneGET(
    Model model, 
    @RequestParam(name = "no", defaultValue = "0", required = false) long no){
    System.out.println(no);
    if(no == 0){
        return "redirect:select.do";
    }
    
    Board obj = bService.selectBoardOne(no);
    model.addAttribute(obj); // key를 생략했으면 변수명 obj가 키값임.
    
    return "board/selectone"; // board 폴더에 selectone.html 생성하기
}

BoardController에 위 코드를 추가한다.

// 하나 조회
@Select({
    " SELECT b.* FROM board b WHERE no = #{no} "
})
public Board selectBoardOne(@Param("no") long no); 

mapper를 생성하고

// 하나 조회
public Board selectBoardOne(@Param("no") long no);

BoardService

@Override
public Board selectBoardOne(long no){
    try{
        return bMapper.selectBoardOne(no);
    }
    catch (Exception e){
        e.printStackTrace();
        return null;
    }
}

BoardServiceImpl에 추가한다.

<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>
    <p th:text="${obj.no}"></p>
    <p th:text="${obj.title}"></p>
    <p th:text="${obj.content}"></p>
    <p th:text="${obj.writer}"></p>
    <p th:text="${obj.hit}"></p>
    <p th:text="${obj.regdate}"></p>
    <a th:href="@{/board/update.do(no=${obj.no})}">수정</a>
    <form th:action="@{/board/delete.do}" method="post">
        <input type="hidden" name="no" th:value="${obj.no}" />
        <input type="submit" value="삭제" />
    </form>
</body>

마지막으로 board 폴더에 selectone.html을 생성하여 위와 같이 작성하면

이렇게 선택한 게시글에 해당하는 정보들이 나오게 된다.


update & delete ( mapper.xml )

@GetMapping(value="/update.do")
public String updateGET(
    Model model, 
    @RequestParam(name = "no", defaultValue = "0", required = false) long no){
    if(no == 0){
        return "redirect:select.do";
    }
    Board obj = bService.selectBoardOne(no);
    model.addAttribute("obj", obj);
    return "/board/update";
}

BoardController에 위 코드를 추가하고

<body>
    <form th:action="@{/board/update.do(no=${obj.no})}" method="post">
        <input type="text" name="no" th:value="${obj.no}" readonly/><br />
        <input type="text" name="title" th:value="${obj.title}" /><br />
        <input type="text" name="content" th:value="${obj.content}" /><br />
        <input type="text" name="writer" th:value="${obj.writer}" /><br />
        <input type="text"  th:value="${obj.hit}" readonly/><br />
        <input type="text", th:value="${obj.regdate}" readonly/><br />
        <input type="submit" value="수정"><br />
    </form>
</body>

update.html을 생성한다.

이런 화면이 나오면 성공이다.


// sql문이 없음 => resources/mappers/파일명Mapper.xml
public int updateBoardOne(@Param("obj") Board obj);

Mapper를 추가한다. 하지만 sql문이 존재하지 않는다.

resources 아래 mapper폴더를 생성하고 boardMapper.xml을 생성한다.

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

application.properties에 위 코드를 작성한다.


deleteBoardOne도 추가하였다

위 사진에서 기존에 사용하던 BoardMapper와 resources폴더에서 만든 boardMapper를 비교해보자.

같은 색의 밑줄친 곳은 꼭 동일해야 한다. 그렇게 해야 서로 연동이 되며 정상적으로 구동이 된다.


// 수정
public int updateBoardOne(Board obj);

// 삭제
    public int deleteBoardOne(long no);

BoardService.java에 추가하고

@Override
public int updateBoardOne(Board obj) {
    try{
        return bMapper.updateBoardOne(obj);
    }
    catch (Exception e){
        e.printStackTrace();
        return 0;
    }
}

@Override
public int deleteBoardOne(long no) {
    try{
        return bMapper.deleteBoardOne(no);
    }
    catch (Exception e){
        e.printStackTrace();
        return 0;
    }
}

BoardServiceImpl에도 추가한다.

@PostMapping(value = "/update.do")
public String updatePOST(@ModelAttribute Board board) {
    int ret = bService.updateBoardOne(board);
    if (ret == 1) {
        return "redirect:selectone.do?no=" + board.getNo(); // 성공시 상세 화면
    }
    return "redirect:update.do?no=" + board.getNo(); // 실패시 수정 화면
}

@PostMapping(value = "/delete.do")
public String deletePOST(
        @RequestParam(name = "no", defaultValue = "0", required = false) long no) {
    System.out.println(no);
    if (no == 0) {
        return "redirect:select.do";
    }
    int ret = bService.deleteBoardOne(no);
    if (ret == 1) {
        return "redirect:select.do";
    }
    return "redirect:boardone.do?no=" + no;
}

마지막으로 BoardController에 update, delete에 대한 POST를 추가한다.


resources 안의 폴더명을 mapper=> mapeprs
application.properties 내의 mapeprs => mappers로 오타 수정


정상적으로 수정됨.

삭제도 정상적으로 수행됨.

0개의 댓글