티스토리 뷰
공통된 부분과 아닌 부분을 분리
어떤 부분을 공통으로 사용하여 추상화 할 것인지 아닌지를 결정해야 한다. 아래와 같은 부분들은 공통으로 추상화할 수 있다.
- Connection 생성
- Statement 준비 및 실행
- ResultSet 생성
- 예외 처리
- Connection, Statement, ResultSet 객체 close
이 미션을 하면서는 기존에 사용하던 jdbcTemplate과 미션 가이드의 도움을 많이 받았다. 실제로 추상화 할 부분과 아닌 부분을 결정하는 것은 추상화 단계의 1단계라는 생각이 들었다.
사용한 자원은 닫는다
Connection, PreparedStatement, ResultSet 등의 사용한 자원은 닫아주어야 한다. 자원이 닫히지 않고 메모리를 계속 차지한다면 메모리 누수가 발생할 수 있고 예상치 못한 문제가 발생할 수 있기 때문이라고 한다. 뭐든지 파일도, 커넥션도 열었던 것은 닫아주자! 기존에는 try~catch~finally
구문으로 자원을 처리하였으나 java7 이상부터는 try with resource 문법이 추가되어 finally 대신 자원을 처리해줄 수 있다.
public void update(String sql, Object... args) {
try (Connection conn = dataSource.getConnection();
PreparedStatement pstmt = createPreparedStatement(conn, sql, args)) {
log.debug("query : {}", sql);
pstmt.executeUpdate();
} catch (SQLException e) {
log.error(e.getMessage(), e);
throw new RuntimeException(e);
}
}
private PreparedStatement createPreparedStatement(Connection conn, String sql, Object... args) throws SQLException {
PreparedStatement pstmt = conn.prepareStatement(sql);
setPreparedStatement(pstmt, args);
return pstmt;
}
private void setPreparedStatement(PreparedStatement pstmt, Object[] args) throws SQLException {
int index = 1;
for (Object arg : args) {
pstmt.setObject(index, arg);
index += 1;
}
}
PreparedStatement에서 셋팅을 해주어야하는 경우 메소드로 분리하여 처리할 수 있다.
가변인자, 제네릭
2~3월에 객체지향 자바 수업에서 가변인자를 처음 봤다. ...
으로 여러개의 인자를 받을 수 있다. 같은 타입의 인자가 몇개가 들어올지 모르는 경우 가변인자를 사용해서 다양하게 함수를 사용할 수 있다. 위에 코드 예시에도 있듯이 가변인자로 받는 경우 배열로 받아진다.
아래의 코드 예시에서 처럼 제네릭 타입을 사용하여 원하는 객체타입을 반환할 수 있다.
템플릿메소드 패턴
해당 메소드를 오버라이드하여 사용하거나 메소드가 1개인 인터페이스를 사용하여 람다식을 사용하여 함수형의 방식으로 인자로 전달해 줄 수 있다.
public interface StateCallBack<T> {
T doInStatement(Statement stmt, ResultSet rs) throws SQLException;
}
// JdbcTemplate Class
private <T> T execute(StateCallBack<T> action, String sql, Object... args) {
try (Connection conn = dataSource.getConnection();
PreparedStatement pstmt = createPreparedStatement(conn, sql, args);
ResultSet rs = pstmt.executeQuery()
) {
return action.doInStatement(pstmt, rs);
} catch (SQLException e) {
log.error(e.getMessage(), e);
throw new RuntimeException(e);
}
}
public <T> T query(String sql, RowMapper<T> rowMapper, Object... args) {
return execute(((stmt, rs) -> {
log.debug("query : {}", sql);
if (rs.next()) {
return rowMapper.mapRow(rs);
}
return null;
}), sql, args);
}
실제로 JdbcTemplate 메소드 안을 살펴보면 아래와 같은 코드로 작성되어 있다.
//실제 jdbcTemplate 라이브러리에서 사용되는 메소드
@FunctionalInterface
public interface ConnectionCallback<T> {
@Nullable
T doInConnection(Connection con) throws SQLException, DataAccessException;
}
결과
기존에는 메소드마다 중복되어 작성되었다. 부분들을 공통된 부분과 아닌 부분으로 분리하여 추상화를 하여 라이브러리화 하여 `후`와 같이 좀 더 변화하는 로직에 집중할 수 있는 코드가 되었다.
// 전
public void insert(User user) {
final String sql = "insert into users (account, password, email) values (?, ?, ?)";
Connection conn = null;
PreparedStatement pstmt = null;
try {
conn = dataSource.getConnection();
pstmt = conn.prepareStatement(sql);
log.debug("query : {}", sql);
pstmt.setString(1, user.getAccount());
pstmt.setString(2, user.getPassword());
pstmt.setString(3, user.getEmail());
pstmt.executeUpdate();
} catch (SQLException e) {
log.error(e.getMessage(), e);
throw new RuntimeException(e);
} finally {
try {
if (pstmt != null) {
pstmt.close();
}
} catch (SQLException ignored) {}
try {
if (conn != null) {
conn.close();
}
} catch (SQLException ignored) {}
}
}
// 후
public void insert(User user) {
final String sql = "insert into users (account, password, email) values (?, ?, ?)";
jdbcTemplate.insert(sql, user.getAccount(), user.getPassword(), user.getEmail());
}
'우아한테크코스 > 레벨4, 레벨5' 카테고리의 다른 글
[sql-tuning 미션] 쿼리 최적화 (0) | 2021.12.02 |
---|---|
[팀 프로젝트] DB Replication ~ AutoConfiguration, OSIV (0) | 2021.12.02 |
[팀 프로젝트] docker에서 EC2로 DB 전환작업 (0) | 2021.10.05 |
[mvc 미션] Servlet, Servlet Container, DispatcherServlet (0) | 2021.10.02 |
[팀 프로젝트] 로깅 설정 개선하기 (3) | 2021.10.02 |
- Total
- Today
- Yesterday
- OS
- python
- 카카오
- 개발공부일지
- 학습로그
- JS
- TCP/IP
- javascript
- React
- 모의면접준비
- 내부코드
- DB
- 글쓰기미션
- 객체지향
- 코드스쿼드
- Spring
- 월간회고
- 알고리즘
- CS
- 마스터즈코스
- TIL
- 인증
- 운영체제
- java
- 우아한테크코스
- JPA
- 우테코수업
- 네트워크
- Transaction
- 회고
일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | 4 | |||
5 | 6 | 7 | 8 | 9 | 10 | 11 |
12 | 13 | 14 | 15 | 16 | 17 | 18 |
19 | 20 | 21 | 22 | 23 | 24 | 25 |
26 | 27 | 28 | 29 | 30 | 31 |