Spring 강의 day 9

주세환·2023년 5월 10일
0

Spring

목록 보기
9/18

Board

목록

@Entity
@Data
@SequenceGenerator(name = "SEQ_BOARD_NO", sequenceName = "SEQ_BOARD_NO", initialValue = 1, allocationSize = 1)
public class Board {
    
    @Id
    @GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "SEQ_BOARD_NO")
    @Column(name = "NO")
    private long no;

    private String title;

    @Lob
    private String content;

    private String writer;

    private long hit;

    @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss.SSS")
    @CreationTimestamp
    private Date regdate;
}

entity에 board.java를 생성한다.


이미 테이블을 만들었기 때문에 application.properties에서 update로 변경하지 않아도 된다.

[no] in table [board]; found [decfloat (Types#NUMERIC)], but expecting [bigint (Types#BIGINT)]

서버를 실행하면 위 오류가 뜰 것이다.

이럴 때는


private BigDecimal no;

private BigDecimal hit;

Board.java를 위 코드로 수정한다.


@Slf4j
@Controller
@RequestMapping(value = "/board2")
@RequiredArgsConstructor
public class Board2Controller {

    final Board2Repository bRepository; // 저장소 객체
    
    // 127.0.0.1:9090/ROOT/board2/selectlist.pknu
    @GetMapping(value="/selectlist.pknu")
    public String selectListGET(Model model){
        try{
            List<Board> list = bRepository.findAll();
            model.addAttribute("list", list);
            return "/board2/selectlist";
        }
        catch(Exception e){
            e.printStackTrace();
            return "redirect:/home.do";
        }
    }
}

Board2Controller.java를 생성하여 selectListGET을 작성하고


<body>
    <h3>목록(board)</h3>
    <a th:href="@{/board2/insertbatch.pknu}"><button>일괄추가</button></a>
    <hr />
    <table>
        <tr th:each="obj : ${list}">
            <td><input type="checkbox" /></td>
            <td th:text="${obj.no.longValue()}"></td>
            <td th:text="${obj.title}"></td>
            <td th:text="${obj.writer}"></td>
            <td th:text="${obj.hit.longValue()}"></td>
            <td th:text="${obj.regdate}"></td>
        </tr>
    </table>
</body>

selectlist.html을 만든 후


@Repository
public interface Board2Repository extends JpaRepository<Board, Long> {
   
}

Board2Repository를 생성한다.


이렇게 나온다.


// select * from board order by no desc
List<Board> findAllByOrderByNoDesc();

Board2Repository.java에 위 코드를 추가하고

try{
    List<Board> list = bRepository.findAllByOrderByNoDesc();
    model.addAttribute("list", list);
    return "/board2/selectlist";
}

Board2Controller를 위처럼 수정한다.


내림차순으로 변경된 것을 확인할 수 있다.


일괄추가

@GetMapping(value="/insertbatch.pknu")
public String insertbatchGET(Model model){
    try{
        return "/board2/insertbatch";
    }
    catch(Exception e){
        e.printStackTrace();
        return "redirect:/home.do";
    }
}

Board2Controller.java에 insertbatchGET을 추가하고


<body>
    <h3>일괄추가</h3>
    <a th:href="@{/board2/selectlist.pknu}"><button>목록으로</button></a>
    <hr />

    <form th:action="@{/board2/insertbatch.pknu}" method="post">
            <th:block th:each="i : ${#numbers.sequence(1,3)}">
                <input type="text" name="title[]" th:value="|t_${i}|" />
                <input type="text" name="content[]" th:value="|c_${i}|"/>
                <input type="text" name="writer[]" th:value="|w_${i}|"/>
                <br />
        </th:block>
        <input type="submit" value="일괄추가" />
    </form>
</body>

insertbatch.html을 추가한다.


게시글목록에서 일괄추가 버튼을 누르면 이렇게 일괄추가할 수 있는 창이 생성된다.


@PostMapping(value="/insertbatch.pknu")
public String insertBatchPOST(
    @RequestParam( name = "title[]") String[] title,
    @RequestParam( name = "content[]") String[] content,
    @RequestParam( name = "writer[]") String[] writer){
    try{
        List<Board> list = new ArrayList<>();
        for(int i = 0; i<title.length; i++){
            Board board = new Board();
            board.setTitle(title[i]);
            board.setContent(content[i]);
            board.setWriter(writer[i]);
            board.setHit(BigDecimal.valueOf(1));
            list.add(board);
        }

        bRepository.saveAll(list);
        return "redirect:/board2/selectlist.pknu";
    }
    catch(Exception e){
        e.printStackTrace();
        return "redirect:/home.do";
    }
}

Board2Controller.java에 insertBatchPOST를 추가한다.


일괄추가를 누르면

이렇게 t_1 ~ t_3 까지 추가가 된다.


일괄삭제

public interface Board2Repository extends JpaRepository<Board, BigDecimal>

Board2Repository에서 Long => BigDecimal로 수정한다


@PostMapping(value="/deletebatch.pknu")
public String deleteBatchPOST(
    @RequestParam(name="chk[]") List<BigDecimal> chk){
    try{
        log.info(chk.toString());
        bRepository.deleteAllById(chk);
        return "redirect:/board2/selectlist.pknu";
    }
    catch(Exception e){
        e.printStackTrace();
        return "redirect:/home.do";
    }
}

Board2Controller.java에 deleteBatchPOST를 추가한다.


<body>
    <h3>목록(board)</h3>
    <a th:href="@{/board2/insertbatch.pknu}"><button>일괄추가</button></a>
    <button th:onclick="formAction1(1)">일괄수정</button>
    <button th:onclick="formAction1(2)">일괄삭제</button>
    <hr />
    
    <form th:action="@{/board2/updatebatch.pknu}" method="post" id="form">
        <table border="1">
            <tr th:each="obj : ${list}">
                <td><input type="checkbox" name="chk[]" th:value="${obj.no.longValue()}"/></td>
                <td th:text="${obj.no.longValue()}"></td>
                <td th:text="${obj.title}"></td>
                <td th:text="${obj.writer}"></td>
                <td th:text="${obj.hit.longValue()}"></td>
                <td th:text="${obj.regdate}"></td>
            </tr>
        </table>
    </form>

    <script th:inline="javascript" type="text/javascript">
        function formAction1(code) {
            const form = document.getElementById('form');
            if(code === 1) {
                form.action = /*[[@{/board2/updatebatch.pknu}]]*/'';
            }
            else if(code === 2) {
                form.action = /*[[@{/board2/deletebatch.pknu}]]*/'';
            }
            form.submit();
        }
    </script>
</body>

selectlist.html을 위 코드처럼 수정, 추가한다.


2개를 체크하고 일괄삭제를 누르면

이렇게 삭제된 것을 볼 수 있다.


일괄수정

final HttpSession httpSession; // 세션객체

@PostMapping(value="/updatebatchaction.pknu")
public String updatePOST(
    @RequestParam( name = "no[]") long[] no,
    @RequestParam( name = "title[]") String[] title,
    @RequestParam( name = "content[]") String[] content,
    @RequestParam( name = "writer[]") String[] writer){
    try{
        List<Board> list = new ArrayList<>();
        for(int i=0; i<no.length; i++){
            // 1. no를 이용하여 기존 정보 가져오기
            Board board = bRepository.findById(BigDecimal.valueOf(no[i])).orElse(null);

            // 2. 기존정보에 위에서 받은 제목, 내용, 작성자 변경하기
            board.setTitle(title[i]);
            board.setContent(content[i]);
            board.setWriter(writer[i]);
            // 3. list에 담기
            list.add(board);
        }
        // 4. 일괄 저장하기
        bRepository.saveAll(list);
        return "redirect:/board2/selectlist.pknu";
    } catch(Exception e){
        return "redirect:/home.do";
    }
}



@SuppressWarnings("unchecked")
@GetMapping(value="/updatebatch.pknu")
public String updateBatchGET(Model model){
    try{
        List<BigDecimal> chk = (List<BigDecimal>) httpSession.getAttribute("chk[]");
        List<Board> list = bRepository.findAllById(chk);
        model.addAttribute("list", list);
        return "/board2/updatebatch";
    } catch(Exception e){
        e.printStackTrace();
        return "redirect:/home.do";
    }
}

@PostMapping(value="/updatebatch.pknu")
public String updateBatchPOST(@RequestParam(name="chk[]") List<BigDecimal> chk){
    try{
        httpSession.setAttribute("chk[]", chk);
        return "redirect:/board2/updatebatch.pknu";
    } catch(Exception e){
        e.printStackTrace();
        return "redirect:/home.do";
    }
}

Board2Controller.java에 updateBatchGET, updateBatchPOST, updatePOST를 추가하고


<body>
    <h3>일괄수정(board)</h3>
    <a th:href="@{/board2/selectlist.pknu}"><button>목록으로</button></a>
    <hr />

    <form th:action="@{/board2/updatebatchaction.pknu}" method="post">
        <table>
            <tr th:each="obj : ${list}">
                <td><input type="text" name="no[]" th:value="${obj.no.longValue()}" readonly/></td>
                <td><input type="text" name="title[]" th:value="${obj.title}" /></td>
                <td><input type="text" name="content[]" th:value="${obj.content}" /></td>
                <td><input type="text" name="writer[]" th:value="${obj.writer}" /></td>
                <td><input type="text" th:value="${obj.hit.longValue()}" readonly/></td>
                <td><input type="text" th:value="${obj.regdate}" readonly/></td>
            </tr>
        </table>
        <input type="submit" value="일괄수정" />
    </form>
</body>

updatebatch.html을 생성하여 작성한다.


43~45를 선택하고 일괄수정을 누르면

updatebatch.pknu로 이동한다.

여기서 no, hit, regdate는 readonly이므로 수정할 수 없다.

이렇게 수정하고 일괄수정을 누르면

이렇게 바뀐 모습을 볼 수 있다.


검색

    // 3. 검색어 타입에 따른 메소드 3개 만들기
    // select * from board where title like '%' || ? || '%' order by no desc
    List<Board> findByTitleIgnoreCaseContainingOrderByNoDesc(String title);
    List<Board> findByContentIgnoreCaseContainingOrderByNoDesc(String content);
    List<Board> findByWriterIgnoreCaseContainingOrderByNoDesc(String writer);

    List<Board> findByTitleIgnoreCaseContainingOrderByNoDesc(String title, Pageable pageable);
    List<Board> findByContentIgnoreCaseContainingOrderByNoDesc(String content, Pageable pageable);
    List<Board> findByWriterIgnoreCaseContainingOrderByNoDesc(String writer, Pageable pageable);

Board2Repository.java에 위 코드를 추가하고


// 127.0.0.1:9090/ROOT/board2/selectlist.pknu
// 1. 전달값 받기 ?page=1&type=writer&text=~~~
@GetMapping(value="/selectlist.pknu")
public String selectListGET(Model model,
    @RequestParam(name="page", defaultValue = "1") int page,
    @RequestParam(name="type", defaultValue = "title") String type,
    @RequestParam(name="text", defaultValue = "") String text ){
    try{
        // 2. 타입에 따라서 다른 메소드 호출
        // findByTitle...()
        List<Board> list = bRepository.findByTitleIgnoreCaseContainingOrderByNoDesc(text);
        if(type.equals("content")){
            list = bRepository.findByContentIgnoreCaseContainingOrderByNoDesc(text);
        }
        else if(type.equals("writer")) {
            list = bRepository.findByWriterIgnoreCaseContainingOrderByNoDesc(text);
        }
        else if(type.equals("title")){
            list = bRepository.findByTitleIgnoreCaseContainingOrderByNoDesc(text);
        }
        model.addAttribute("list", list);
        return "/board2/selectlist";
    }
    catch(Exception e){
        e.printStackTrace();
        return "redirect:/home.do";
    }
}

Board2Controller.java의 selectListGET을 위처럼 수정한다.


제목이 1이 포함된 게시글만 select한다.

작성자 이름에 ㅁ이 포함된 게시글만 select한다.


페이지네이션

// 127.0.0.1:9090/ROOT/board2/selectlist.pknu
// 1. 전달값받기 ?page=1&type=writer&text=ㅓㅓㅗㅓㅗ
@GetMapping(value="/selectlist.pknu")
public String selectListGET(
        Model model, 
        @RequestParam(name = "page", defaultValue = "0") int page,
        @RequestParam(name = "type", defaultValue = "title") String type,
        @RequestParam(name = "text", defaultValue = "") String text ) {
    try {
        if(page == 0) { // ? 가 없으면
            return "redirect:/board2/selectlist.pknu?page=1&type=title&text=";
        }
        PageRequest pageRequest = PageRequest.of((page-1), 10);

        List<Board> list = bRepository.findByTitleIgnoreCaseContainingOrderByNoDesc(text, pageRequest);
        long total = bRepository.countByTitleIgnoreCaseContainingOrderByNoDesc(text);

        if(type.equals("content")) {
            list = bRepository.findByContentIgnoreCaseContainingOrderByNoDesc(text, pageRequest);
            total = bRepository.countByContentIgnoreCaseContainingOrderByNoDesc(text);
        }
        else if(type.equals("writer")) {
            list = bRepository.findByWriterIgnoreCaseContainingOrderByNoDesc(text, pageRequest);
            total = bRepository.countByWriterIgnoreCaseContainingOrderByNoDesc(text);
        }
        model.addAttribute("list", list);
        model.addAttribute("pages", (total-1)/10 + 1);
        return "/board2/selectlist";
    }
    catch(Exception e){
        e.printStackTrace();
        return "redirect:/home.do";
    }
}

Board2Controller.java의 selectListGET을 위처럼 수정, 추가하고


<body>
    <h3>목록(board)</h3>
    <a th:href="@{/board2/insertbatch.pknu}"><button>일괄추가</button></a>
    <button th:onclick="formAction1(1)">일괄수정</button>
    <button th:onclick="formAction1(2)">일괄삭제</button>
    <hr />

    <form th:action="@{/board2/selectlist.pknu}" method="get">
        <input type="hidden" name="page" value="1" />
        <select name="type">
            <option value="title">제목</option>
            <option value="content">내용</option>
            <option value="writer">작성자</option>
        </select>
        <input type="text" name="text" placeholder="검색어" />
        <input type="submit" value="검색" />
    </form>
    
    <form th:action="@{/board2/updatebatch.pknu}" method="post" id="form">
        <table border="1">
            <tr th:each="obj : ${list}">
                <td><input type="checkbox" name="chk[]" th:value="${obj.no.longValue()}"/></td>
                <td th:text="${obj.no.longValue()}"></td>
                <td th:text="${obj.title}"></td>
                <td th:text="${obj.writer}"></td>
                <td th:text="${obj.hit.longValue()}"></td>
                <td th:text="${obj.regdate}"></td>
            </tr>
        </table>
    </form>

    <th:block th:each="num : ${#numbers.sequence(1, pages)}">
        <a th:href="@{/board2/selectlist.pknu( page=${num}, type=${param.type}, text=${param.text})}" th:text="${num}"></a>
    </th:block>

    <script th:inline="javascript" type="text/javascript">
        function formAction1(code) {
            const form = document.getElementById('form');
            if(code === 1) {
                form.action = /*[[@{/board2/updatebatch.pknu}]]*/'';
            }
            else if(code === 2) {
                form.action = /*[[@{/board2/deletebatch.pknu}]]*/'';
            }
            form.submit();
        }
    </script>
</body>

selectlist.html을 위처럼 수정, 추가한다.

10개씩 페이지네이션이 된 모습을 볼 수 있다.


구매

@Data
@Immutable // 뷰일경우 추가 => 조회만 가능한 엔티티
@Entity
@Table(name = "BOARD1_VIEW")
public class Board1View {
    
    @Id
    @Column( name = "NO")
    private Long no = 0L;

    @Column(name="TITLE")
    private String title= null;
}

entity에 Board1View.java

@Data
@Immutable   //뷰일경우 추가 => 조회만 가능한 엔티티...
@Entity
@Table(name = "PURCHASEVIEW")
public class PurchaseView {
    
    @Id
	@Column(name = "NO") 
	private BigDecimal no;

    @Column(name = "CNT") 
    private BigDecimal cnt;

    @Column(name="ITEMNO")
    private BigDecimal itemNo;

    @Column(name="ITEMPRICE")
    private BigDecimal itemPrice;

    @Column(name = "CUSTOMERID")
    private String customerId = null;

    @Column(name = "CUSTOMERNAME")
    private String customerName = null;

    @Column(name = "ITEMNAME")
    private String itemName = null;

    @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss.SSS")
    @Column(name = "REGDATE")
    private Date regdate;
}

PurchaseView.java를 생성한다.


public interface PurchaseViewRepository extends JpaRepository<PurchaseView, BigDecimal>{
    
}

PurchaseViewRepository.java도 생성한다.


@Slf4j
@Controller
@RequestMapping(value = "/purchaseview")
@RequiredArgsConstructor
public class PurchaseViewController {

    final PurchaseViewRepository pvRepository;

    // 127.0.0.1:9090/ROOT/purchaseview/selectlist.pknu
    @GetMapping(value="/selectlist.pknu")
    public String selectlistGET(Model model){
        try{
            List<PurchaseView> list = pvRepository.findAll();
            model.addAttribute("list", list);
            return "/purchase/selectlist";
        }catch(Exception e){
            e.printStackTrace();
            return "redirect:/home.do";
        }
    }
}

PurchaseViewController.java


<body>
    <h3>주문내역(purchaseview)</h3>
    <hr />

    <table border="1">
        <thead>
            <tr>
                <th>주문번호</th>
                <th>주문수량</th>
                <th>물품번호</th>
                <th>물품가격</th>
                <th>고객아이디</th>
                <th>고객이름</th>
                <th>물품이름</th>
                <th>주문일자</th>
            </tr>
        </thead>
        <tbody>
            <tr th:each="obj :${list}">
                <td th:text="${obj.no.longValue()}"></td>
                <td th:text="${obj.cnt.longValue()}"></td>
                <td th:text="${obj.itemNo.longValue()}"></td>
                <td th:text="${obj.itemPrice.longValue()}"></td>
                <td th:text="${obj.customerId}"></td>
                <td th:text="${obj.customerName}"></td>
                <td th:text="${obj.itemName}"></td>
                <td th:text="${obj.regdate}"></td>
            </tr>
        </tbody>
    </table>
</body>

selectlist.html

5개의 파일을 생성하면

주문내역이 나오게 된다.


실습

<form th:action="@{/purchaseview/selectlist.pknu(num=1)}" method="get">
    <input type="text" placeholder="주문번호 입력" />
    <input type="text" placeholder="물품이름 입력" />
    <input type="submit" value="주문번호와 물품이름이 정확하게 일치하는 것만 조회" />
</form>
<hr />

<form th:action="@{/purchaseview/selectlist.pknu(num=1)}" method="get">
    <input type="text" placeholder="주문번호 입력" />
    <input type="text" placeholder="물품이름 입력" />
    <input type="submit" value="주문번호와 물품이름 둘 중 하나 이상 일치하는 것만 조회" />
</form>        
<hr />

<form th:action="@{/purchaseview/selectlist.pknu(num=1)}" method="get">
    <input type="text" placeholder="주문번호를 ,로 구분해서 입력" />
    <input type="submit" value="주문번호에 해당하는 항목만 조회" />
</form>
<hr />

<form th:action="@{/purchaseview/selectlist.pknu(num=1)}" method="get">
    <input type="text" placeholder="물품이름을 ,로 구분해서 입력" />
    <input type="submit" value="제목이 해당하는 항목만 조회" />
</form>
<hr />

해당하는 코드 짜기.

풀이

<form th:action="@{/board1view/selectlist.pknu}" method="get">
    <input type="hidden" name="num" value="1" />
    <input type="text" name="no" placeholder="글번호입력" />
    <input type="text" name="title" placeholder="제목입력" />
    <input type="submit" value="글번호와 제목이 정확하게 일치하는 것만 조회" />
</form>
<hr />

<form th:action="@{/board1view/selectlist.pknu}" method="get">
    <input type="hidden" name="num" value="2" />
    <input type="text" name="no" placeholder="글번호입력" />
    <input type="text" name="title" placeholder="제목입력" />
    <input type="submit" value="글번호 제목 둘 중 하나이상 일치하는 것만 조회" />    
</form>
<hr />

<form th:action="@{/board1view/selectlist.pknu}" method="get">
    <input type="hidden" name="num" value="3" />
    <input type="text" name="no1" placeholder="글번호를 ,로 구분해서 입력" />
    <input type="submit" value="글번호에 해당하는 항목만 조회" />    
</form>
<hr />

<form th:action="@{/board1view/selectlist.pknu}" method="get">
    <input type="hidden" name="num" value="4" />
    <input type="text" name="title" placeholder="제목을 ,로 구분해서 입력" />
    <input type="submit" value="제목이 해당하는 항목만 조회" />    
</form>    
<hr />

각각 name을 지정해준다.


@Repository
public interface Board1ViewRepository extends JpaRepository<Board1View, Long>{
       
        // 0 or 없으면
        List<Board1View> findAllByOrderByNoDesc();

        // 1번
        List<Board1View> findByNoAndTitleOrderByNoDesc (long no, String title);
    
        // 2번
        List<Board1View> findByNoOrTitleOrderByNoDesc (long no, String title);
    
        // 3번
        List<Board1View> findByNoIn(long[] no);
    
        // 4번
        List<Board1View> findByTitleIn(String[] title);
}

jpa문을 작성한다.


// 127.0.0.1:9090/ROOT/board1view/selectlist.pknu
@GetMapping(value="/selectlist.pknu")
public String selectlistGET( Model model,
@RequestParam(name="num", defaultValue = "0") int num,
@RequestParam(name="title", defaultValue = "") String title,
@RequestParam(name="no", defaultValue = "0") long no,
@RequestParam(name="no1", defaultValue = "")String no1 // split을 사용하기 위해 String으로 정의
){
    try{
        List<Board1View> list = b1vRepository.findAll();
        if(num == 1){
            list = b1vRepository.findByNoAndTitleOrderByNoDesc(no, title);
        }
        else if(num == 2){
            list = b1vRepository.findByNoOrTitleOrderByNoDesc(no, title);
        }
        else if(num == 3){
            String[] arr = no1.split(","); // split을 사용하여 String[] arr 배열에 저장
            long[] arrl = new long[arr.length]; // 깡통 배열을 생성하여 long[] arrl에 넣을 것이다.
            for(int i =0; i<arr.length; i++){   // arr의 길이만큼 반복
                arrl[i] = Long.parseLong(arr[i]);   // arrl에 넣음
            }
            list = b1vRepository.findByNoIn(arrl);
        }
        else if(num == 4){
            String[] t = title.split(",");
            list = b1vRepository.findByTitleIn(t);
        }
        model.addAttribute("list", list);
        return "/board1view/selectlist";
    }catch(Exception e){
        e.printStackTrace();
        return "redirect:/home.do";
    }
}

Board1ViewController에 작성.


결과

1번 문제


2번 문제


3번 문제


4번 문제

0개의 댓글