코딩항해기
[Spring] JDBCTemplate : KeyHolder 본문

[Spring] 템플릿 패턴 : JDBCTemplate 적용 (DAO 고도화)
템플릿 패턴복잡한 로직, 반복되는 로직을 캡슐화하는 패턴으로 중복되는 코드를 줄이고 유지보수를 편리하게 할 수 있다. GoF 디자인패턴 : 템플릿 패턴알고리즘의 구조를 메서드에 정의하고,
minibcake.tistory.com
KeyHolder가 필요한 이유
가게 정보를 가진 Store 테이블과 해당 Store의 영업 정보를 가지고 있는 StoreWork 테이블이 있다. 이 테이블은 부모자식관계로 StoreWork가 Store의 PK를 FK로 갖는 구조다.
가게를 새롭게 만들때 가게 정보와 가게 영업 정보를 모두 입력받아 두 테이블에 데이터를 넣게되는데, 이때 Store에 데이터를 넣는 것까지는 문제가 없지만 StoreWork 데이터를 추가할 때 문제가 발생한다. insert (jdbcTemplate.update())의 반환 값은 데이터 변동 개수이기 때문에 방금 전 추가된 Store의 PK를 알 수 없는 것이다. (PK는 시스템에서 지정해주는 값이기 때문이다.)
기존에는 가장 높은 PK넘버를 구해 반환받아 사용했기 때문에 트랜잭션이 필수로 필요하고, 한 가게가 등록 중이라면 다른 가게는 등록할 수 없었다. 이 때 KeyHolder를 사용하면 PK번호를 반환 받을 수 있다.
KeyHolder 구동
JDBCTemplate에서 제공하는 방식으로 KeyHolder를 사용하면 insert된 데이터를 반환받을 수 있다. KeyHolder는 GeneratedKeyHolder를 통해 구현할 수 있다. 구현한 KeyHolder 객체와 PreparedStatementCreator 객체를 update()파라미터로 넣어 실행하면 KeyHolder에 지정된 데이터가 저장되어 .getKey()를 통해 테이터를 반환 받을 수 있다.
KeyHolder 문법
람다식 (JAVA 8이상)
public void insert(final Member member) {
// 자동 생성된 키 값을 저장하기 위한 홀더 생성
KeyHolder keyHolder = new GeneratedKeyHolder();
jdbcTemplate.update(connection -> {
// 쿼리 실행 후 생성된 ID 값을 반환받기 위해 두 번째 파라미터 지정
PreparedStatement pstmt = connection.prepareStatement(
"INSERT INTO MEMBER (EMAIL, PASSWORD, NAME, REGDATE) " +
"VALUES (?, ?, ?, NOW())",
new String[]{"ID"} // 자동 생성된 키 컬럼명 지정
);
// PreparedStatement에 파라미터 값 설정
pstmt.setString(1, member.getEmail()); // 이메일
pstmt.setString(2, member.getPassword()); // 비밀번호
pstmt.setString(3, member.getName()); // 이름
return pstmt;
}, keyHolder);
// 생성된 키 값을 가져와서 member 객체에 설정
member.setId(keyHolder.getKey().longValue());
}
익명클래스
public void insert(final Member member) {
// 자동 생성된 키 값을 저장하기 위한 홀더 생성
KeyHolder keyHolder = new GeneratedKeyHolder();
jdbcTemplate.update(new PreparedStatementCreator() {
@Override
public PreparedStatement createPreparedStatement(Connection con) throws SQLException {
// 쿼리 실행 후 생성된 ID 값을 반환받기 위해 두 번째 파라미터 지정
PreparedStatement pstmt = con.prepareStatement(
"INSERT INTO MEMBER (EMAIL, PASSWORD, NAME, REGDATE) " +
"VALUES (?, ?, ?, NOW())",
new String[]{"ID"} // 자동 생성된 키 컬럼명 지정
);
// PreparedStatement에 파라미터 값 설정
pstmt.setString(1, member.getEmail()); // 이메일
pstmt.setString(2, member.getPassword()); // 비밀번호
pstmt.setString(3, member.getName()); // 이름
return pstmt;
}
}, keyHolder);
// 생성된 키 값을 가져와서 member 객체에 설정
Number keyValue = keyHolder.getKey(); // 자동 생성된 키 값 반환
member.setId(keyValue.longValue()); // Number 타입을 long으로 변환하여 설정
}
'Spring' 카테고리의 다른 글
[Spring] MyBatis (인텔리제이 Intellij) (2) | 2024.11.04 |
---|---|
[SpringBoot] HikariCP (0) | 2024.10.30 |
[Spring] 경로 메서드 기록 (ServletContext, request, System) (0) | 2024.10.22 |
[Spring] 파일 입출력 MultipartFile (0) | 2024.10.21 |
[Spring] AOP @Order 실행 우선 순위 설정 (0) | 2024.10.20 |