mybatis 쿼리 실행과 동시에 키, 값 가져오기 (데이터 insert 후 auto increment 키값 가져오기)

Jinju Bae·2022년 2월 23일
0

게시판을 만드는 과정에서 파일 업로드를 해야 할 일이 생겼다.
게시글을 작성하고, 동시에 파일 업로드를 하는 과정에서
생성된 게시글의 글번호 값을 파일 테이블에서 참조해야 하는 것이다.

테이블을 먼저 살펴보자.

게시판 테이블




글번호에 해당하는 boardId 는 auto_increment 로 1부터 자동 증가하게 했고, 따라서 row 를 insert 할 때는 boardId 는 insert 하지 않는다.

CREATE TABLE tbl_board(
boardId Long auto_increment,
title varchar (10000) not null,
replyContent varchar (10000) not null,
name varchar (10000) not null,
read varchar (10000) not null default 0,
primary key(boardId)
);
INSERT INTO tbl_board( title, content, name, read) VALUES ('제목1', '내용1', '이름1',0);

파일 업로드

게시글을 업로드하는 페이지에서 파일 업로드도 동시에 진행할 것이다.
다음은 파일 테이블이다.



테이블을 생성하는 sql 문을 살펴보자.

CREATE TABLE TBL_FILE
(
    FILE_NO NUMBER auto_increment,          --파일 번호
    boardId NUMBER NOT NULL,                --게시판 번호
    ORG_FILE_NAME VARCHAR2(260) NOT NULL,   --원본 파일 이름
    STORED_FILE_NAME VARCHAR2(36) NOT NULL, --변경된 파일 이름
    FILE_SIZE NUMBER,                       --파일 크기
    REGDATE DATE DEFAULT SYSDATE NOT NULL,  --파일등록일
    DEL_GB VARCHAR2(1) DEFAULT 'N' NOT NULL,--삭제구분
    PRIMARY KEY(FILE_NO)                    --기본키 FILE_NO
);

문제는 컨트롤러에서 postMapping 을 통해 게시글 업로드, 파일 업로드를 동시에 진행해야 하는데 게시글의 boardId 는 게시글을 업로드 해야 auto increment 로 생기기 때문에 파일 업로드 메소드를 실행할 때는 그 값이 존재하지 않아 boardId 를 insert 할 수 없다는 것이다.


구체적으로 이해하기 위해 컨트롤러 코드를 살펴보자.

    @PostMapping("/upload")
    public String uploadBoard(   
        @RequestPart MultipartFile file, // 게시글 업로드 페이지에서 첨부된 파일을 받아옴
        Board board // 게시글 업로드 페이지에서 입력된 제목, 작성자, 글내용을 한꺼번에 받아옴
        ) throws IOException {
            
            String path = "C:\\"+"pic\\"; // 파일을 저장할 경로
            if(!file.isEmpty()){
                String filename = file.getOriginalFilename();
                String uploadPath = path + filename;
                // 파일을 저장하기 위한 파일 객체 생성
                File files = new File(uploadPath);
                try {
                    // 파일 저장
                    file.transferTo(files);
                } catch (IllegalStateException e) {
                    e.printStackTrace();
                } catch (IOException e) {
                    e.printStackTrace();
                }
                      
            }
            service.uploadBoard(board); // 게시글 업로드 메소드 실행
            service.uploadFile(file); // 파일 업로드 메소드 실행

        return "/boards/upload";
    }

아래에서 3번째, 2번째 줄을 보면 게시글 업로드 메소드를 실행한 후 파일 업로드 메소드를 실행하는 것을 볼 수 있다. uploadBoard, uploadFile 메소드의 sql 문은 다음과 같다.
    <insert id="uploadBoard" parameterType="wedatalab.bulletinboard.domain.Board">
        INSERT INTO tbl_board (title, content, name, read)
        VALUES
        (#{title}, #{content}, #{name}, 0);
    </insert>

    <insert id="uploadFile" parameterType="wedatalab.bulletinboard.domain.Board">
        INSERT INTO tbl_file (boardId, org_file_name, stored_file_name)
        VALUES(#{boardId}, #{filename}, #{filename});
    </insert>

컨트롤러에서 postMapping 을 하면 두 메소드가 동시에 실행되기 때문에 uploadFile 메소드를 실행시 uploadBoard 메소드를 실행할 때 생성된 boardId 를 받아올 수가 없다.

그래서 다음과 같이 매개변수로 받아오는 boardId 값이 없다는 오류가 발생한다.

There was an unexpected error (type=Internal Server Error, status=500).
nested exception is org.apache.ibatis.reflection.ReflectionException: There is no getter for property named 'boardId' in 'class


해결방법

이를 해결하는 방법은 useGeneratedKeys="true", keyProperty 속성을 사용하는 것이다.
uploadBoard 메소드 sql 문에 이 속성을 추가해보자.

    <insert id="uploadBoard" useGeneratedKeys="true" keyProperty="boardId" parameterType="wedatalab.bulletinboard.domain.Board">
        INSERT INTO tbl_board (title, content, name, read)
        VALUES
        (#{title}, #{content}, #{name}, 0);
    </insert>

그러면 게시판 업로드 시 auto increment 로 생성된 boardId 를 매개변수로 받아 uploadFile 메소드를 실행할 수 있게 되는 것이다.

profile
진주개발일지 (珍珠開發日誌)

0개의 댓글