Spring에서 제공하는 쿼리 실행 방법을 알아보겠습니다.
JdbcTemplate을 이용한 변경 쿼리 실행
INSERT, UPDATE, DELETE 쿼리는 update() 메서드를 사용합니다.
* int update(String sql)
* int update(String sql, Object... args)
update() 메서드는 쿼리 실행 결과로 변경된 행의 개수를 리턴합니다. update() 메서드의 사용 예를 알아봅시다.
public class MemberDao {
private JdbcTemplate jdbcTemplate;
...
public void update(Member member) {
jdbcTemplate.update(
"update MEMBER set NAME = ?, PASSWORD = ? where EMAIL = ?",
member.getName(), member.getPassword(), member.getEmail());
}
}
PrepareStatementCreator를 이용한 쿼리 실행
앞서 쿼리의 인덱스 파라미터 "?" 에 member.getName(), member.getPassword(), member.getEmail()을 사용하는데 대부분 이렇게 쿼리의 인덱스 파라미터의 값을 전달합니다.
PreparedStatement의 set 메서드를 사용해서 직접 인덱스 파라미터의 값을 설정해야 할 때도 있습니다. 이 경우 PreparedStatementCreator를 인자로 받는 메서드를 이용해서 직접 PreParedStatement를 생성하고 설정해야 합니다.
package org.springframework.jdbc.core;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.SQLException;
@FunctionalInterface
public interface PreparedStatementCreator {
PreparedStatement createPreparedStatement(Connection con) throws SQLException;
}
PreparedStatementCreator 인터페이스의 createPreparedStatement() 메서드는 Connection 타입의 파라미터를 갖습니다.
PreparedStatementCreator를 구현한 클래스는 createPreparedStatement() 메서드의 파라미터로 전달받는 Connection을 이용해서 PreparedStatement 객체를 생성하고 인덱스 파라미터를 알맞게 설정한 뒤에 리턴하면 됩니다.
public void insert(Member member) {
jdbcTemplate.update(new PreparedStatementCreator() {
@Override
public java.sql.PreparedStatement createPreparedStatement(Connection con) throws SQLException {
// 파라미터로 전달받은 Connection을 이용해서 PreparedStatement 생성
PreparedStatement pstmt = con
.prepareStatement("inesrt into MEMBER(EMAIL, PASSWORD, NAME, REGDATE) values (?,?,?,?)");
// 인덱스 파라미터의 값 설정
pstmt.setString(1, member.getEmail());
pstmt.setString(2, member.getPassword());
pstmt.setString(3, member.getName());
pstmt.setTimestamp(4, Timestamp.valueOf(member.getRegisterDateTime()));
// 생성한 pstmt 객체 리턴
return pstmt;
}
});
}
JdbcTemplate 클래스가 제공하는 메서드 중에서 PreparedStatementCreator 인터페이스를 파라미터로 갖는 메서드는 다음과 같습니다.
* List<T> query(PreparedStatementCreator psc, RowMapper<T> rowMapper)
* int update(PreparedStatementCreator psc)
* int update(PreparedStatementCreator psc, KeyHolder generatedKeyHolder)
3번째 메서드는 자동 생성되는 키값을 구할 때 사용합니다.
INSERT 쿼리 실행 시 KeyHolder를 이용해서 자동 생성 키값 구하기
MySQL의 AUTO_INCREMENT 칼럼은 행이 추가되면 자동으로 값이 할당되는 칼럼으로서 주요 키 칼럼에 사용됩니다.
create table spring5fs.MEMBER(
ID int auto_increment primary key,
EMAIL varchar(255),
PASSWORD varchar(100),
NAME varchar(100),
REGDATE datetime,
unique key(EMAIL)
) engine=InnoDB character set = utf8;
AUTO_INCREMENT와 같은 자동 증가 칼럼을 가진 테이블을 삽입하면 해당 칼럼의 값이 자동으로 생성됩니다. 따라서 INSERT 쿼리에 자동 증가 칼럼에 해당하는 값을 지정하지 않습니다.
jdbcTemplate.update(new PreparedStatementCreator() {
@Override
public java.sql.PreparedStatement createPreparedStatement(Connection con) throws SQLException {
// 파라미터로 전달받은 Connection을 이용해서 PreparedStatement 생성
PreparedStatement pstmt = con
.prepareStatement("inesrt into MEMBER(EMAIL, PASSWORD, NAME, REGDATE) values (?,?,?,?)");
// 인덱스 파라미터의 값 설정
pstmt.setString(1, member.getEmail());
pstmt.setString(2, member.getPassword());
pstmt.setString(3, member.getName());
pstmt.setTimestamp(4, Timestamp.valueOf(member.getRegisterDateTime()));
// 생성한 pstmt 객체 리턴
return pstmt;
}
});
그렇다면, 쿼리 실행 후에 생성된 키값을 알고 싶다면 어떻게 해야 할까요? update() 메서드는 변경된 행의 개수를 리턴할 뿐 생성된 키값을 리턴하진 않습니다.
JdbcTemplate는 자동으로 생성된 키값을 구할 수 있는 방법을 제공합니다. KeyHolder를 사용하면 다음 코드와 같이 MemberDao의 insert() 메서드에서 삽입하는 Member 객체의 ID 값을 구할 수 있습니다.
public void insert(Member member) {
KeyHolder keyHolder = new GeneratedKeyHolder();
jdbcTemplate.update(new PreparedStatementCreator() {
@Override
public java.sql.PreparedStatement createPreparedStatement(Connection con) throws SQLException {
// 파라미터로 전달받은 Connection을 이용해서 PreparedStatement 생성
PreparedStatement pstmt = con
.prepareStatement("inesrt into MEMBER(EMAIL, PASSWORD, NAME, REGDATE) values (?,?,?,?)"
, new String[] {"ID"} );
// 인덱스 파라미터의 값 설정
pstmt.setString(1, member.getEmail());
pstmt.setString(2, member.getPassword());
pstmt.setString(3, member.getName());
pstmt.setTimestamp(4, Timestamp.valueOf(member.getRegisterDateTime()));
// 생성한 pstmt 객체 리턴
return pstmt;
}
}, keyHolder);
Number keyValue = keyHolder.getKey();
member.setId(keyValue.longValue());
}
1. GeneratedKeyHoler 객체를 생성하는데 이 클래스는 자동 생성된 키 값을 구해주는 KeyHolder의 구현체입니다.
2. update()는 PreparedStatementCreator 객체와 KeyHolder 객체를 파라미터로 갖습니다.
3. PreparedStatemnetCreator 임의 클래스를 이용해서 PreParedStatement 객체를 직접 생성합니다. Connection의 preparedStatement() 메서드를 이용해서 PreparedStatement 객체를 생성하는데 두 번째 파라미터로 String 배열인 {"ID"}를 주었습니다. 이 두 번째 파라미터는 자동 생성되는 키 칼럼 목록을 지정할 때 사용합니다. MEMBER 테이블은 ID 칼럼이 자동 증가 키 칼럼이므로 두 번째 파라미터 값으로 {"ID"}를 주었습니다.
4. JdbcTemplate.update() 메서드의 두 번째 파라미터로 생성한 KeyHolder 객체를 전달합니다.
KeyHolder에 보관된 키 값은 getKey() 메서드를 이용해서 구합니다. Number 타입을 리턴하므로 intValue(), longValue() 메서드를 통해 키 값을 원하는 값으로 변환할 수 있습니다.
람다식으로 바꿔보기
KeyHolder keyHolder = new GeneratedKeyHolder();
jdbcTemplate.update((Connection conn) -> {
PreparedStatement pstmt = conn.prepareStatement("insert into MEMBER (EMAIL, PASSWORD, NAME, REGDATE) " +
"values (?, ?, ?, ?)",
new String[] {"ID"} );
// 인덱스 파라미터의 값 설정
pstmt.setString(1, member.getEmail());
pstmt.setString(2, member.getPassword());
pstmt.setString(3, member.getName());
pstmt.setTimestamp(4, Timestamp.valueOf(member.getRegisterDateTime()));
// 생성한 pstmt 객체 리턴
return pstmt;
}, keyHolder);
'Spring' 카테고리의 다른 글
[Spring] Spring DB 연동 과정에서 발생하는 Exception (0) | 2024.02.26 |
---|---|
[Spring] Spring DB - 쿼리 실행 테스트 (1) | 2024.02.25 |
[Spring] Spring JdbcTemplate - qureyForObject 메서드 (0) | 2024.02.19 |
[Spring] Spring JDBCTemplate 쿼리실행 (0) | 2024.02.19 |
[Spring] Spring DB 연동 - Tomcat JDBC의 프로퍼티 (0) | 2024.02.18 |