JDBC
- Java 어플리케이션과 DB 연결 및 작업 수행
JDBC(Java Database Connectivity)는 자바의 표준 API로, 자바 애플리케이션과 데이터베이스 간의 연결과 데이터베이스 작업을 수행하는 데 사용됩니다.
Intro. Java 기본 JDBC와 Spring JDBC
순수 JDBC 외에 Spring에서 JDBC를 제공합니다.
앞으로 예시는 Spring의 JDBC를 예로 들겠습니다
Spring JDBC를 사용하면, 코드의 양이 줄어들고, 데이터베이스 리소스 관리와 예외 처리가 자동화되며, 반복적인 작업이 줄어듭니다.
즉, 개발자는 SQL 쿼리와 비즈니스 로직에 더 집중할 수 있게 됩니다.
예를 들면 ResultSet
은 데이터베이스로부터 반환된 결과 집합을 나타내는 객체입니다.
순수 JDBC에서는 개발자가 ResultSet
에서 컬럼의 값을 읽고 필요한 객체에 수동으로 매핑해야 했습니다.
그러나 Spring JDBC를 사용하면, RowMapper
를 구현하여 이 작업을 단순화할 수 있습니다.
RowMapper
는 ResultSet
의 각 행을 원하는 형태의 객체로 자동 변환해주는 역할을 합니다.
1. NamedParameterJdbcTemplate
:
Spring JDBC에서 제공하는 클래스로 SQL 쿼리를 실행하는데 사용됩니다.
이 클래스는 파라미터를 이름으로 지정할 수 있게 해주며, JDBC 코드에서 발생할 수 있는 리소스 관리와 오류 처리를 담당합니다.
용도: 데이터베이스와의 커뮤니케이션에서 SQL 쿼리를 실행하는데 사용됩니다.
예제 코드:
- update
private final NamedParameterJdbcTemplate namedParameterJdbcTemplate;
private Member update(Member member) {
var sql = String.format("UPDATE %s set email = :email, nickname = :nickname, birthday = :birthday WHERE id = :id", TABLE);
SqlParameterSource params = new BeanPropertySqlParameterSource(member);
namedParameterJdbcTemplate.update(sql, params);
return member;
}
- 직접 쿼리를 날리는 방법 : SQL과 데이터를 맵핑해서 query를 직접
private final NamedParameterJdbcTemplate namedParameterJdbcTemplate;
public Optional<Member> findById(Long id) {
var sql = String.format("SELECT * FROM %s WHERE id = :id ", TABLE);
var params = new MapSqlParameterSource()
.addValue("id", id);
List<Member> members = namedParameterJdbcTemplate.query(sql, params, ROW_MAPPER);
// jdbcTemplate.query의 결과 사이즈가 0이면 null, 2 이상이면 예외
Member nullableMember = DataAccessUtils.singleResult(members);
return Optional.ofNullable(nullableMember);
}
2. SimpleJdbcInsert
:
Spring JDBC에서 제공하는 또 다른 클래스로, 개발자가 SQL 쿼리를 직접 작성하지 않고도 데이터베이스에 객체를 삽입할 수 있게 해줍니다.
용도: 데이터베이스에 새로운 레코드를 삽입하는데 사용됩니다.
예제 코드:
아래 예제 코드에서 보면, JDBC 템플릿을 인자로 넣음으로서, SQL 없이 엔티티에 접근 하는 것을 볼 수 있습니다
private Member insert(Member member) {
SimpleJdbcInsert jdbcInsert = new SimpleJdbcInsert(namedParameterJdbcTemplate.getJdbcTemplate())
.withTableName(TABLE)
.usingGeneratedKeyColumns("id");
SqlParameterSource params = new BeanPropertySqlParameterSource(member);
var id = jdbcInsert.executeAndReturnKey(params).longValue();
return Member.builder()
.id(id)
.nickname(member.getNickname())
.email(member.getEmail())
.birthday(member.getBirthday())
.build();
}
여기서 궁금했던 것은 NamedParameterJdbcTemplate
를 이용해서 쿼리를 변경 할 수 있는가였습니다
결론적으로 변경은 되지만 자동 생성된 key를 추출하는 것은 SimpleJdbcInsert
를 사용할 때 보다 복잡해집니다.
JDBC 표준에는 자동 생성된 키를 반환하는 방법이 명시되어 있지 않기 때문에, 데이터베이스 벤더마다 처리 방식이 다릅니다.
private Member insert(Member member) {
String insertSql = "INSERT INTO " + TABLE + "(nickname, email, birthday) VALUES(:nickname, :email, :birthday)";
MapSqlParameterSource params = new MapSqlParameterSource();
params.addValue("nickname", member.getNickname());
params.addValue("email", member.getEmail());
params.addValue("birthday", member.getBirthday());
namedParameterJdbcTemplate.update(insertSql, params);
// After insert operation, you need to somehow fetch the generated ID
// This depends on your specific DBMS and setup and is not trivial in a standard way
// For now, in this example, we will skip this part
return Member.builder()
.id(null) // this should be replaced with real id obtained from DB after insert
.nickname(member.getNickname())
.email(member.getEmail())
.birthday(member.getBirthday())
.build();
}
위와 같이 코드를 작성하는 방식은 코드가 더 단순해질 수 있지만, 데이터베이스에서 생성된 ID를 다시 가져오는 방법이 일관성이 없고 복잡하다는 단점이 있습니다.
SimpleJdbcInsert
는 이러한 단점을 해결하고자 만들어졌구나 싶었습니다
부족한 점이나 잘못 된 점을 알려주시면 시정하겠습니다 :>
'DEV > Java' 카테고리의 다른 글
Spring Security (0) | 2023.07.04 |
---|---|
Easy Random (0) | 2023.06.02 |
데이터 변환 with Spring (0) | 2023.05.27 |
데이터 검증 with Spring (0) | 2023.05.27 |
Spring MVC 예외 처리 및 상태 코드 매핑 가이드 (0) | 2023.05.26 |