JDBC
- 자바에서 데이터베이스에 접속할 수 있도록 하는 자바 API로, JDBC는 데이터베이스에서 자료를 쿼리하거나 업데이터하는 방법을 제공한다.
- 스프링은 더 쉽게 JDBC를 사용할 수 있도록 JdbcTemplate 클래스를 제공하며, JdbcTemplate은 JDBC를 사용할 때 요구되는 반복되는 코드없이도 개발자가 관계형 데이터베이스에 대한 SQL 연산을 수행할 수 있는 방법을 제공한다.
JdbcTemplate이 없다면
- 데이터베이스 연결(connection), 명령문(statement) 생성과 쿼리 수행, 결과(result set) 처리, 사용한 자원들을 닫고 클린업하는 코드를 전부 작성해야 한다.
- 또한, 연결이나 명령문 등의 객체를 생성할 때 또는 쿼리를 수행할 때 반드시 SQLException 예외를 처리해주어야 한다.
- SQLException은 catch 블록으로 반드시 처리해야 하는 checked 예외지만, 데이터베이스 연결 생성 실패나 작성 오류가 있는 쿼리와 같은 대부분의 문제들은 catch 블록에서 해결될 수 없으므로, 현재 메서드를 호출한 상위 코드로 예외처리를 넘겨야 한다.
JdbcTemplate
- 명령문이나 데이터베이스 연결 객체를 생성하는 코드와 메서드의 실행이 끝난 후 그런 객체들을 클린업하는 코드가 없고, catch 블록에서 올바르게 처리할 수 없는 예외를 처리하는 코드도 없다.
- 따라서 개발자는 쿼리의 수행과 그 결과를 객체로 생성하는 것에만 집중할 수 있다.
@Repository
@RequiredArgsConstructor
public class JdbcRepository {
private final JdbcTemplate jdbc;
public Member save(Member member) {
jdbc.update(
"insert into Member (id, name) values (?, ?)",
member.getId(),
member.getName());
return hello;
}
}
조회
- 객체가 저장된 컬렉션을 반환하는 findAll() 메서드는 JdbcTemplate의 query() 메서드를 사용한다.
- query() 메서드는 첫 번째 인자로 쿼리를 수행하는 SQL을, 두 번째 인자로 스프링의 RowMapper 인터페이스를 구현한 mapRowToObject 메서드를 받는다.
public Iterable<Member> findAll() {
return jdbc.query("select id, name from Member", this::mapRowToObject);
}
private Member mapRowToObject(ResultSet rs, int rowNum) throws SQLException {
return new Member(rs.getString("id"), rs.getString("name");
}
- mapRowToObject() 메서드는 쿼리로 생성된 ResultSet의 행 개수만큼 호출되며, 결과 세트의 모든 행을 각각 객체로 생성하고 List에 저장한 후 반환한다.
- 또한, query()에서는 해당 쿼리에서 요구하는 매개변수들의 내역을 마지막 인자로 받을 수 있다.
public Member findById(String id) {
return jdbc.queryForObject("select id, name from Member where id=?", this::mapRowToObject, id);
}
- findById() 메서드는 하나의 객체만 반환하므로, query() 대신 queryForObject() 메서드를 사용한다.
- queryForObject() 메서드는 query()와 동일하게 실행되지만, 객체의 List를 반환하는 대신 하나의 객체만 반환한다.
- queryForObject()의 첫 번째와 두 번째 인자는 query()와 동일하며, 세 번째 인자로 검색할 행의 id를 전달한다.
추가
- JdbcTemplate의 update() 메서드는 데이터베이스에 데이터를 추가하거나 변경하는 어떤 쿼리에도 사용할 수 있다.
- update() 메서드는 결과 세트의 데이터를 객체로 생성할 필요가 없으므로, 수행될 SQL을 포함하는 문자열과 쿼리 매개변수에 지정할 값만 인자로 전달한다.
public Member save(Member member) {
jdbc.update(
"insert into Hello (id, name) values (?, ?)",
member.getId(),
member.getName());
return member;
}
스키마 정의
- schema.sql 이라는 이름의 파일을 애플리케이션 classpath의 루트 경로에 있으면 애플리케이션이 시작될 때 schema.sql 파일의 SQL이 사용 중인 데이터베이스에서 자동 실행된다.
- 또한, 스프링 부트는 애플리케이션이 시작될 때 data.sql이라는 이름의 파일도 자동으로 실행하는데, data.sql을 이용해서 데이터베이스에 데이터를 미리 추가할 수 있다.