PROJECT #5 - JOIN

김형우·2022년 4월 12일
0

New Project

목록 보기
6/12

답글 작성을 위해서 새 엔티티 생성 -> BOARD 엔티티의 BNO를 외부키로 가져옴 (답글 엔티티 기준 ManyToOne) -> 답글작성

0. 엔티티 생성

  • 외래키를 엔티티로 가져온다는 뜻은 모든 데이터를 가져오는것이 아니라 엔티티 형태의 기본키 컬럼만 가져오는것이고, 타입은 BIGINT로 잡힌다.
    BOARD10의 모든것을 가져오는것이 아님, 즉, BOARD10의 PK인 BNO만 가져온다.

0-1. BoardReplyEntity.java

  • 외부키로 BoardEntity 전체가 들어오는 모양이지만 DB에서는 BNO만 가져오고, BOARD의 타입은 BIGINT로 잡힌다. (위 이미지 참고)
package com.example.entity;

import java.util.Date;

import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.ManyToOne;
import javax.persistence.SequenceGenerator;
import javax.persistence.Table;

import org.hibernate.annotations.CreationTimestamp;
import org.springframework.format.annotation.DateTimeFormat;

import lombok.Data;

@Entity
@Data
@Table(name = "BOARD10_REPLY")
// 생성할 시퀀스
@SequenceGenerator(name = "SQE1", sequenceName = "SEQ_BOARD10_REPLY_RNO", allocationSize = 1, initialValue = 1)
public class BoardReplyEntity {

    @Id
    @Column(name = "RNO")
    @GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "SQE1")
    private long no;

    @Column(name = "RCONTENT", length = 300)
    private String content;

    @Column(name = "RWRITER", length = 50)
    private String writer;

    @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss.SSS")
    @CreationTimestamp
    @Column(name = "RREGDATE")
    private Date date;

    // 외부키, 보드 자체가 들어오는 개념
    @ManyToOne
    @JoinColumn(name = "BOARD")
    private BoardEntity board;

}

0-2. BoardEntity.java

  • BoardEntity에도 BoardReplyEntity와의 관계를 정의하고, List의 형태로 해당 PK에 속한 BoardReplyEntity들을 담는다.
    : BoardEntity의 입장에서는 OneToMany의 관계
    : 12번글에 적힌 댓글 2개를 replyList라는 객체명에 List의 형태로 담는것
package com.example.entity;

import java.util.ArrayList;
import java.util.Date;
import java.util.List;

import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.Lob;
import javax.persistence.OneToMany;
import javax.persistence.SequenceGenerator;
import javax.persistence.Table;

import org.hibernate.annotations.CreationTimestamp;
import org.springframework.format.annotation.DateTimeFormat;

import lombok.Data;

@Entity
@Data
// 테이블명
@Table(name = "BOARD10")
// 시퀀스 생성
@SequenceGenerator(name = "SEQ_BOARD", // 시퀀스
        sequenceName = "SEQ_BOARD10_NO", // 시퀀스명
        allocationSize = 1, // 증가값
        initialValue = 1) // 시작값
public class BoardEntity {

    @Id
    @Column(name = "BNO") // 컬럼명
    @GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "SEQ_BOARD") // 시퀀스 적용
    private Long no; // 타입 변수

    @Column(name = "BTITLE", length = 200) // VARCHAR2(200)
    private String title = null;

    @Lob // CLOB
    @Column(name = "BCONTENT")
    private String content;

    @Column(name = "BWRITER")
    private String writer;

    @Column(name = "BHIT")
    private long hit = 1L;

    @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss.SSS")
    @CreationTimestamp // CURRENT_DATE
    @Column(name = "BREGDATE")
    private Date regdate;

    // BOARD10 입장에서는 OneToMany
    // 만약 10번글에 답글이 세개가 달렸다면,
    // 답글들은 10번이라는 외부키를 받을것이고,
    // 10번 글은 답글의 PK인 no를 List로 가진다.
    @OneToMany(mappedBy = "board")
    private List<BoardReplyEntity> replyList = new ArrayList<>();

}

1. 사용

1-1. BoardReplyRepository.java

답글 작성을 위해서 새 엔티티 생성 -> BOARD 엔티티의 BNO를 외부키로 가져옴 (답글 엔티티 기준 ManyToOne) -> 답글작성

package com.example.repository;

import java.util.List;

import com.example.entity.BoardReplyEntity;

import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.stereotype.Repository;

@Repository
public interface BoardReplyRepository extends JpaRepository<BoardReplyEntity, Long> {

    // 원본글번호가 일치하는 댓글 개수
    // List<BoardReplyEntity> replyList = new ArrayList<>();
    // Board안에 no를 객체로 잡을때는 언더바_를 사용한다
    List<BoardReplyEntity> findByBoard_noOrderByNoDesc(long bno);

}

1-2. BoardController.java

package com.example.controller;

import java.util.List;

import com.example.entity.BoardEntity;
import com.example.entity.BoardReplyEntity;
import com.example.repository.BoardReplyRepository;
import com.example.repository.BoardRepository;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.domain.PageRequest;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;

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

    // global.properties 사용
    @Value("${board.page.count}")
    int PAGECNT;

    @Autowired
    BoardRepository bRepository;

    @Autowired
    BoardReplyRepository brRepository;

    // 답글 POST
    @PostMapping(value = "/insertreply")
    public String insertReplyPOST(
            @ModelAttribute BoardReplyEntity reply) {
        System.out.println("=== reply === " + reply);
        System.out.println("=== reply.toString() === " + reply.toString());

        brRepository.save(reply);

        return "redirect:/board/selectone?no=" + reply.getBoard().getNo();
    }

    // 추가 GET
    @GetMapping(value = { "/insert" })
    public String insertGET() {
        return "board/insert";
    }

    // 추가 POST
    @PostMapping(value = "/insert")
    public String insertPOST(
            @ModelAttribute BoardEntity board) {
        // save(entity객체) == INSERT INTO
        bRepository.save(board);
        return "redirect:/board/insert";
    }

    // 목록 GET
    @GetMapping(value = "/selectlist")
    public String selectlistGET(Model model,
            @RequestParam(value = "txt", defaultValue = "") String title,
            @RequestParam(value = "page", defaultValue = "1") int page) {

        // 페이지네이션
        // (시작페이지(0부터), 개수)
        PageRequest pageRequest = PageRequest.of(page - 1, PAGECNT);
        // findAll == SELECT * FROM BOARD10
        // List<BoardEntity> list = bRepository.selectBoardList(title);
        List<BoardEntity> list = bRepository.findByTitleContainsOrderByNoDesc(title, pageRequest);
        model.addAttribute("list", list);

        // 페이지개수
        long total = bRepository.countByTitleContaining(title);
        model.addAttribute("pages", (total - 1) / PAGECNT + 1);
        // System.out.println("=== list === " + list);
        return "board/selectlist";
    }

    // 상세 GET
    @GetMapping(value = "/selectone")
    public String selectoneGET(Model model,
            @RequestParam(name = "no") long no) {
        BoardEntity board = bRepository.findById(no).orElse(null);
        // 댓글 개수
        List<BoardReplyEntity> repList = brRepository.findByBoard_noOrderByNoDesc(board.getNo());
        model.addAttribute("repList", repList);
        model.addAttribute("board", board);
        // System.out.println("=== board === " + board);

        return "board/selectone";
    }
}
profile
The best

0개의 댓글