20220929 [Spring Boot, Oracle, MyBatis]

Yeoonnii·2022년 10월 3일
0

TIL

목록 보기
37/52
post-thumbnail

ModelAndView Class

Spring공식문서 - ModelAndView Class

ModelAndView Class는 Controller에서 modelView를 한번에 반환가능하게 하는 Class
➡️ model로 전송할 정보 + 화면View에 표시하는 작업을 동시에 진행해야하는 경우 ModelAndView 클래스를 사용하여 Controller가 단일 반환값으로 modelView를 한번에 반환할 수 있도록 한다

ModelAndView로 데이터 보내기

BoardController.java

ModelAndView(viewName, modelName, modelObject)
➡️ html 파일명, 전송모델명 , 전송모델객체

ModelAndView("board/insert1", "obj", board);
//  127.0.0.1:8080/BOOT1/board/ insert1.do
    @GetMapping("/insert1.do")
    public ModelAndView insertGET(){

        // model.addAttribute("obj", obj)를 사용하는 경우 board객체만 리턴 가능!
        // ModelAndView 이용하여 객체와 view 동시에 리턴해보기

        BoardDTO board = new BoardDTO(); //객체 만들기
        board.setTitle("dd2");
        board.setContent("ddd3");
        board.setWriter("ddd");
        
        // return new ModelAndView(viewName, modelName, modelObject)
        // html 파일명, 전송모델명 , 전송모델객체
        // 전송할것도 있고 화면도 표시해야하는 작업 진행시 ModelAndView 사용
        return new ModelAndView("board/insert1", "obj", board);
    }

insert1.html

form 태그에 th:object="${obj}” 명시해주고
th:field="${obj.title}” 사용하여 출력해준다

<!DOCTYPE html>
<html lang="ko" xmlns:th="http://www.thymeleaf.org">

<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>
    <a th:href="@{/seller/home.do}">홈으로</a>
    <hr />
    게시판글쓰기
    <hr />
    
    <form th:action="@{/board/insert1.do}" th:object="${obj}" method="post">
            <input type="text" th:field="${obj.title}" name="name" placeholder="제목"  />
            <input type="text" th:field="${obj.content}" name="content" placeholder="내용" />
            <input type="number" th:field="${obj.writer}" name="price" placeholder="작성자"  /><br />
        <hr />
        <input type="submit" value="일괄추가" />
    </form>
</body>

</html>

📃결과


ModelAndView로 데이터 받아서 추가

ModelAndView는 데이터를 view로 전송해주는것 뿐만 아니라 view에서 데이터를 되돌려 받기도 쉽다

checkbox로 선택한 데이터 받기

BoradDTO.java

체크박스의 항목 / 체크된 여러개의 항목을 저장할 배열 생성

// 체크할 항목들
    String[] chkLabel = {"국어", "영어", "수학", "과학"};

// 체크된 항목을 보관(저장)할 배열
    String[] choiceChk;

insert1.html

체크박스 생성 후 여러개의 데이터 선택 + 선택한 데이터 Controller로 보내주기
th:field="*{choiceChk}”* = 반복자 = 여러개의 데이터 선택 가능

...
            <input type="text" th:field="${obj.title}" name="name" placeholder="제목"  />
            <input type="text" th:field="${obj.content}" name="content" placeholder="내용" />
            <input type="text" th:field="${obj.writer}" name="price" placeholder="작성자"  /><br />
            <!-- DTO의 항목 기반으로 체크박스 생성한다 -->
            <input type="checkbox" name="choiceChk" th:each="tmp : ${obj.chkLabel}" th:text="${tmp}" th:value="${tmp}" th:field="*{choiceChk}" /> 
...
        <input type="submit" value="일괄추가" />
    </form>
</body>

</html>

BoardController.java

View에서 받아온 데이터 출력해보기

    @PostMapping(value = "/insert1.do")
    public String insert1POST(
            @ModelAttribute BoardDTO board) {
        System.out.println(board.toString());
        return "redirect:/board/insert1.do";
    }

radio로 선택한 데이터 받기

BoardDTO.java

라디오의 항목 / 라디오의 항목을 저장할 변수 생성

    // 라디오 항목을 보관할 문자(radio 사용하기 = 1개)
    String choiceRad;

    // select[]
    String choiceSel;
    String[] choiceSel1;

insert1.html

radio 생성 후 데이터 선택 + 선택한 radio의 데이터 Controller로 보내주기

 <input type="radio" name="choiceRad" th:each="tmp : ${obj.chkLabel}" th:text="${tmp}" th:value="${tmp}" th:field="*{choiceRad}" />

select로 선택한 데이터 받기

1개 데이터 선택용 변수, 여러개의 데이터 선택용 배열형태 변수 생성

    //1개 데이터 선택시
    String choiceSel;
    
    // 여러개의 데이터 선택시 = select[]
    String[] choiceSel1;

insert1.html

 <!-- 1개의 항목 선택시 -->
            <select th:field="${obj.choiceSel}">
                <option th:each="tmp:${obj.chkLabel}" th:value="${tmp}" th:text="${tmp}" ></option>
            </select>
            <br />
<!-- 여러개의 항목 선택시 => select에 multiple 사용 = option 여러개 선택 가능 -->
            <select th:field="${obj.choiceSel1}" multiple>
                <option th:each="tmp:${obj.chkLabel}" th:value="${tmp}" th:text="${tmp}" ></option>
            </select>
            <br />

ModelAndView로 데이터 일괄추가

  • 여러개의 BoardDTO를 일괄저장하기 위한 BoardDTO N개 보관 가능 객체 = BoardListDTO생성
  • form 하나가 모델 하나라고 생각하면 된다!

    form 하나인 경우 : th:object="${obj}”
    form 두개인 경우 : th:object="${obj1}” / th:object="${obj2}”

게시판 회원수정시 ModelAndView 사용하면 기존 정보가 뿌려져 있을것
보통의 insert같은 경우 input칸이 비워져 있어도 상관 없지만 회원정보수정 같은 경우 기존 회원 정보를 받아와서 뿌려주고 수정된 값을 가져가야 하니 ModelAndView를 사용해주면 좋다

BoardListDTO.java

BoardDTO를 N개 보관하기 위한 BoardListDTO.java

package com.example.dto;

import java.util.List;

import lombok.Data;

@Data
public class BoardListDTO {
    
    // BoardDTO를 N개 보관
    List<BoardDTO> list;
}

BoardController.java

  • BoardListDTO = BoardDTO를 List형태로 가질 수 있게 만듬
  • view에 전송모델객체 전송시 list를 던지면 안됨!
    ➡️ list를 보관할 수 있는 객체 BoardListDTO를 생성해서 던져야 여러개의 BoardDTO를 List형태로 보관 가능하다
  • 데이터 일괄 추가시 같은 컬럼끼리 배열형태로 담아줬었는데 이건 여러개의 DTO형태 받고싶은 상황!
    // BoardDTO를 N개 보관
    // 127.0.0.1:8080/BOOT1/board/ insertall1.do
    @GetMapping(value = "/insertall1.do")
    public ModelAndView insertallGET() {

        // 일괄추가 항목 만들기
        List<BoardDTO> list = new ArrayList<>();

        for(int i=0; i<3; i++){
        BoardDTO board = new BoardDTO(); // 객체 만들기
        board.setTitle(board.getTitle());
        board.setContent(board.getContent());
        board.setWriter(board.getWriter());
        list.add(board);
        }

        // BoardDTO N개 보관 가능 객체
        BoardListDTO obj = new BoardListDTO();
        obj.setList(list);

        // list를 보관할 수 있는 객체 BoardListDTO를 생성하여 보관

        return new ModelAndView("board/insertall1", "obj", obj);
    }

insertall1.html

Controller에서 BoardListDTOobj로 넘겨줬다
➡️ View 에서 obj를 반복하면 BoardListDTO가 반복된다!
BoardDTO를 반복하여 입력받아야 하니 obj가 아닌 obj.list를 반복하여 입력받는다

💡 th:each="tmp, idx : ${obj.list}" = obj반복이 아닌 obj.list를 반복!

<!DOCTYPE html>
<html lang="ko" xmlns:th="http://www.thymeleaf.org">

<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>
    <a th:href="@{/seller/home.do}">홈으로</a>
    <hr />
    게시판글쓰기
    <hr />
    
    <form th:action="@{/board/insertall1.do}" th:object="${obj}" method="post">
        <th:block th:each="tmp, idx : ${obj.list}">
            <input type="text" th:name="|list[${idx.index}].title|" th:value="${tmp.title}" placeholder="제목" />
            <input type="text" th:name="|list[${idx.index}].content|" th:value="${tmp.content}" placeholder="내용" />
            <input type="text" th:name="|list[${idx.index}].writer|" th:value="${tmp.writer}" placeholder="작성자"/>
            <br />
        </th:block>
        <hr />
        <input type="submit" value="일괄추가" />
    </form>
</body>

</html>

출력화면에 3개의 입력창이 생성된 이유는 BoardController에서 for반복문의 길이를 3으로 지정하여 list를 생성해줬기 때문이다 ➡️ for(int i=0; i<3; i++)

BoardController.java

DB에 저장하기
1. view에서 전송한 데이터를 컨트롤러에서 받고
2. 일괄추가할 항목 생성 List<BoardDTO> list
3. 받은데이터를 BoardDTO에 담아준 후
3. ModelAndView 리턴

for(BoardDTO obj : boardlist.getList()) = boardlist.getList()에서 차례로 객체를 꺼내 BoardDTO obj에 넣는다는 뜻이다
🌎 [Java] for구문에서 콜론(:)의 기능 - for(Object : List)

view 에서 Controller로 model을 받을 때 @ModelAttribute BoardListDTO boardlist를 사용한다

    @PostMapping(value = "/insertall1.do")
    public String insertall1POST(@ModelAttribute BoardListDTO boardlist){
    
        System.out.println("===========BoardListDTO=============");
        System.out.println(boardlist.getList().toString());
        List<BoardDTO> list = new ArrayList<>();

        for(BoardDTO obj : boardlist.getList()){
            
            System.out.println("===========obj.toString()=============");
            System.out.println(obj.toString());

            list.add(obj);
        };
        bMapper.insertBoardBatch(list);

        return "redirect:/board/insertall1.do";
    }


Scheduling 구현

Scheduling(스케쥴링)은 반복되는 일을 수행할때 수행되는 시점을 크론표현식을 이용하여 지정해준다

scheduler/CrawScheduler.java

@Scheduled(cron = "*초 *분 *시 *일 *월 *주 *년")

  • 5초 단위로 실행되는 스케쥴링 ➡️ (cron = "*/5 * * * * *")
  • 실시간 실행되는 스케쥴링 ➡️ @Scheduled(cron = "* * * * * *")
  • 매일 정시에 실행되는 스케쥴링 ➡️ @Scheduled(cron = "* * *0 * * *")
package com.example.scheduler;

import java.util.Date;

import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;

@Component
public class CrawScheduler {
    

    @Scheduled(cron = "*/5 * * * * *")
    public void crawDate1(){
        // System.out.println( new Date().toString() );

        // axios => okhttp3
    }
}

application.java

스케쥴링 활성화 + 환경설정 추가

// 스케쥴링 활성화
@EnableScheduling

환경설정에 추가

"com.example.scheduler"

결과
설정한 시간마다 동기화 되는것을 확인 할 수 있다

[ORACLE] 장바구니 기능 추가

물품을 회원이 장바구니에 담는 기능
➡️ 장바구니 기능을 즐겨찾기/주문 기능으로도 활용 가능하다

거래내역이나 주문취소내역 같은 경우는 취소된 거래내역이나 주문내역도 조회가 가능하여야 한다 ➡️ 삭제의 개념이 아니다!

이처럼 거래나 주문이 취소 되어도 기록을 남겨두고 조회할 수 있어야 하는 경우,
새 컬럼을 생성하여 거래, 주문의 상태를 타입값으로 지정해준다

장바구니 테이블 생성

장바구니 정보를 저장할 테이블 생성
➡️ 장바구니 = 회원+물품

CREATE TABLE CARTTBL(
     NO NUMBER PRIMARY KEY,
     ITEMNO NUMBER,
     USERID VARCHAR2(30),
     REGDATE DATE DEFAULT CURRENT_DATE,
     CONSTRAINT FK_CART_ITEM_NO FOREIGN KEY(ITEMNO) REFERENCES ITEMTBL(NO),
     CONSTRAINT FK_CART_MEMBER_ID FOREIGN KEY(USERID) REFERENCES MEMBERTBL(USERID)
);

장바구니 조회용 VIEW생성

장바구니 조회용 view 생성 (필터 조건은 없음)
VIEW에서 조회 가능한 내용
➡️ 물품번호, 물품명, 물품가격 / 회원아이디, 회원연락처, 회원등록일

  1. 아이템(ITEMTBL)-카트(CARTTBL)를 조인
SELECT I.NO ITEMNO, I.NAME, I.PRICE, C.NO
FROM ITEMTBL I
INNER JOIN CARTTBL C
ON I.NO = C.ITEMNO;
  1. 카트(CARTTBL)와 멤버(MEMBERTBL)를 조인
SELECT M.USERID, M.PHONE, M.REGDATE, C.NO
FROM MEMBERTBL M
INNER JOIN CARTTBL C
ON M.USERID = C.USERID;
  1. 1과 2를 조인
CREATE OR REPLACE VIEW CART_VIEW AS
SELECT M.USERID, M.PHONE, M.REGDATE, I.NO ITEMNO, I.NAME, I.PRICE, C.NO
FROM CARTTBL C
INNER JOIN ITEMTBL I ON I.NO = C.ITEMNO
INNER JOIN MEMBERTBL M ON M.USERID = C.USERID;

VIEW 생성시 오류 발생

🌎 ORA-00957: 열명이 중복되었습니다

[ORACLE] 물품 카테고리 기능 추가

물품 분류표 테이블 생성하기

CATETBL = AAA 의류, BBB 식품, CCC 가전제품

CREATE TABLE CATETBL(
    ID VARCHAR2(3),
    NAME VARCHAR2(50),
    
    CONSTRAINT PK_CATETBL_ID PRIMARY KEY(ID)
);

데이터 추가

INSERT ALL
    INTO CATETBL(ID, NAME) VALUES('AAA', '의류')
    INTO CATETBL(ID, NAME) VALUES('BBB', '식품' )
    INTO CATETBL(ID, NAME) VALUES('CCC', '가전제품')
SELECT * FROM DUAL;
COMMIT;

물품과 분류표를 연결하는 테이블 생성

CATEITEMTBL 생성하여 CATETBLITEMTBL 의 PK를 외래키 제약조건을 걸어 연결

CREATE TABLE CATEITEMTBL(
    NO number,
    CATEID VARCHAR2(3),
    ITEMNO NUMBER,
    CONSTRAINT PK_CATEITEM_NO PRIMARY KEY(NO),
    CONSTRAINT FK_CATE_ID FOREIGN KEY (CATEID) REFERENCES CATETBL(ID),
    CONSTRAINT FK_ITEM_NO FOREIGN KEY (ITEMNO) REFERENCES ITEMTBL(NO)
);

0개의 댓글