DataBase

[H2 DB] insert시 auto increment인 sequence 값을 바로 받아 오는 법

bkuk 2023. 3. 28. 09:49

DAO 메서드

지금까지 DAO(Data Access Object) 클래스의 메서드를 아래와 같이 설계해왔다.

public void insert( Ans ans ) { ... }
public Ans select(String answerId ) { ... }
public List<Ans> selectAll(String questionId) { ... }

 

테이블 구조

DTO(Data Transfer Object) 클래스인 Ans의 테이블 구조는 아래와 같다.

CREATE TABLE ANSWERS (
	answerId 			bigint				auto_increment,
	writer				varchar(30)			NOT NULL,
	contents			varchar(5000)		NOT NULL,
	createdDate			timestamp			NOT NULL,
	questionId			bigint				NOT NULL,				
	PRIMARY KEY         (answerId)
);

 

사용 컨트롤러

이를 사용하는 컨트롤러(Controller)를 살펴보자.

Ans 객체를 생성 후, AnsDao 클래스를 통해 DB에 접근해 insert를 진행한 것을 볼 수 있다.

public class CreateAnsController implements Controller {
	@Override
	public String execute(HttpServletRequest req, HttpServletResponse resp) throws Exception {
		[..생략..]
        Ans ans = new Ans(
        		user.getUserId(),
        		req.getParameter("contents"), 
        		req.getParameter("questionId") );
        
        AnsDao ansDao = new AnsDao();
        ansDao.insert(ans);
        
		return "redirect:/";
	}

}

 

기존 insert 메서드()

Dao 클래스의 insert 메서드는 아래와 같다.

여기서 컬럼 answerId에 대해서는 auto increment 속성을 부여함으로써, DB에 insert 된 후 select 하기 전까지는 알 수 없다.

public void insert( Ans ans ) {
    JdbcTemplate jdbcTemplate = new JdbcTemplate();
    String sql = "INSERT INTO ANSWERS (writer, contents, createdDate, questionId) VALUES (?, ?, now(), ?)";
    jdbcTemplate.update(
            sql, 
            ans.getWriter(),
            ans.getContents(),
            ans.getQuestionId()
    );
}

 

변경 insert 메서드()

하지만, 여기서 ResultSet을 통해 해당 값을 가져올 수 있다.

public void update(PreparedStatementCreator psc, KeyHolder holder) {
    try (Connection conn = ConnectionManager.getConnection()) {
        PreparedStatement ps = psc.createPreparedStatement(conn);
        ps.executeUpdate();

        ResultSet rs = ps.getGeneratedKeys();
        if (rs.next()) {
            holder.setId(rs.getLong(1));
        }
        rs.close();
    } catch (SQLException e) {
        throw new DataAccessException(e);
    }
}

 

추가 DTO  클래스(Key Holder 클래스)

위를 보면 알 수 있듯이, KeyHolder라는 클래스를 파라미터로 갖는 메서드로 확인할 수 있다.

해당 클래스 구조는 아래와 같다.

package next.model;

public class Result {
    private boolean status;
    private String message;

    private Result(boolean status) {
        this(status, "");
    }

    private Result(boolean status, String message) {
        this.status = status;
        this.message = message;
    }

    public static Result ok() {
        return new Result(true);
    }

    public static Result fail(String message) {
        return new Result(false, message);
    }

    public boolean isStatus() {
        return status;
    }

    public String getMessage() {
        return message;
    }

    @Override
    public String toString() {
        return "Result [status=" + status + ", message=" + message + "]";
    }
}