try - catch - finally
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);
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) {}
}
}
위의 형식은 일반적으로 볼 수 있는 try-catch-finally 구조이다.
이런 형식으로 작성시 finally에서 null을 체크하고 반환을 해야 하는 반복적인 코드가 나오게 된다.
그렇다면 위와 같은 코드들의 중복을 줄일 수 없을까?
첫번째로 간단하게 생각해 볼 수 있는것은 메서드 분리이다.
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);
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 {
closes(conn, pstmt);
}
}
private void closes(Connection conn, PreparedStatement pstmt) {
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 (?, ?, ?)";
Connection conn = null;
PreparedStatement pstmt = null;
try {
conn = dataSource.getConnection();
pstmt = conn.prepareStatement(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 {
closes(conn, pstmt);
}
}
private void closes(Connection conn, PreparedStatement pstmt) {
preparedStatementClose(pstmt);
connectionClose(conn);
}
private void connectionClose(Connection conn) {
try {
if (conn != null) {
conn.close();
}
} catch (SQLException ignored) {
}
}
private void preparedStatementClose(PreparedStatement pstmt) {
try {
if (pstmt != null) {
pstmt.close();
}
} catch (SQLException ignored) {
}
}
close 하는 부분이 중복처럼 보이기때문에 메서드를 하나로 통일하면 아래와 같다.
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(sq
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 {
closes(conn, pstmt);
}
}
private void closes(AutoCloseable... autoCloseables) {
for (AutoCloseable autoCloseable: autoCloseables) {
close(autoCloseable);
}
}
private void close(AutoCloseable conn) {
try {
if (conn != null) {
conn.close();
}
} catch (Exception e) { }
}
try-with-resources
중복을 많이 줄이고 다른곳에서도 재사용이 가능해졌지만 finally에서 신경을 계속써야하는 부분은 변함이 없다. 그리고 이러한 부분에서 개발자들의 실수가 발생해 메모리 릭이 발생한다.
이펙티브 자바에 적힌바에 의한다면 2007년 자바의 라이브러리는 1/3정도만 제대로 close 했다고 한다.
이러한걸 한번에 해결해주는 문법이 있다.
try-with-resources 라는 문법이다.
public void example() {
try(여기서 자원할당) {
//코드작성
} catch(Exception e) {
// 에러핸들링
}
}
try뒤에있는 ()안에 있는 자원들을 자동으로 해제시켜준다.
public void insert(User user) {
final String sql = "insert into users (account, password, email) values (?, ?, ?)";
try(Connection conn = dataSource.getConnection();
PreparedStatement pstmt = conn.prepareStatement(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);
}
}
위와 같이 작성하면 에러가 발생하기 쉬워지는 null이 나오지 않고 자원도 신경쓰지 않아도 자동으로 해제시켜준다.
즉, 개발자의 실수를 줄여주고 간결한 코드를 볼 수 있도록 해준다.
close 되는건 Autoclosable 인터페이스를 구현한 객체들만 종료된다.
지원은 자바7 버전부터 지원이 되기 시작했다.
결론 : try - with - resources 를 사용하자
이펙티브자바 아이템9에 자세한 설명이 있다.
'프로그래밍언어 > Java' 카테고리의 다른 글
[Java] LocalTime, LocalDate, LocalDateTime을 이용한 시간 관리하기 (0) | 2024.03.30 |
---|---|
[Java] 실행시간 측정하기 (0) | 2024.03.25 |
[Java] JUnit 이란? (1) | 2022.03.20 |
[Java] 문자열에서 원하는 문자 추출하기 (0) | 2022.02.10 |
자바(Java) String 문자열 비교하기 (0) | 2022.02.10 |
댓글