3. 템플릿 - 다시 보는 초난감 DAO

이유석·2022년 5월 19일
0

Book - Toby's Spring

목록 보기
14/20
post-thumbnail

1장에서 초난감 DAO 코드에 DI를 적용하여 관심이 다른 코드를 다양한 방법으로 분리하고, 확장과 변경에 용이하게 대응할 수 있는 설계구조로 개선하는 작업을 진행했다.

개방 폐쇄원칙

  • 확장에는 자유롭게 열러있고, 변경에는 굳게 닫혀 있다는 객체지향 설계의 핵심 원칙
  • 어떤 부분은 변경을 통해 그 기능이 다양해지고 확장하려는 성질을 갖는다.
  • 어떤 부분은 고정되어 있고 변하지 않으려는 성질을 갖는다.
  • 개방폐쇄원칙은
    • 변화의 특성이 다른 부분을 구분해준다.
    • 각각 다른 목적과 다른 이유에 의해 다른 시점에 독립적으로 변경될 수 있는 효율적인 구조를 만들어준다.

템플릿

  • 개방폐쇄원칙에서 고정되어 있는 성질을 갖고, 일정한 패턴으로 유지되는 특성을 가진 부분을 독립시켜 효과적으로 활용할 수 있도록 하는 방법이다.

다시보는 초난감 DAO

이전장에서 UserDao 코드의 DB 연결과 관련된 여러가지 개선 작업을 했지만, 아직 예외상황에 대한 처리부분이 부족하다.

3.1.1 예외처리 기능을 갖춘 DAO

DB 커넥션이라는 제한적인 리소스를 공유해 사용하는 서버에서 동작하는 JDBC 코드가 지켜야할 원칙

  • 예외 처리
  • 코드 중간에 어떤 이유로든 예외가 발생했을 경우에도 사용한 리소스를 반드시 반환하도록 만들어야 하기 때문이다.

JDBC 수정 기능의 예외 처리 코드

public void deleteAll() throws SQLException {
	Connection c = this.dataSource.getConnection();

	// 여기서 예외가 발생하면, 공유 리소스인 ps, c를 반환하지 않고 메소드 실행이 종료된다.
	PreparedStatement ps = c.prepareStatement("delete from users");

	ps.executeUpdate();

	ps.close();
    c.close();
}
  • 서버에서는 제한된 개수의 DB 커넥션을 만들어서 재사용 가능한 풀로 관리한다.
  • 오류가 날 때마다 미처 반환되지 못한 Connection이 증가할 수록, 커넥션 풀에 여유가 없어지고 리소스가 모자란다는 심각한 오류를 내며 서버가 중단될 수 있다.
  • 그래서 이런 JDBC 코드에서는 어떤 상황에서도 가져온 리소스를 반환하도록 try/catch/finally 구문 사용을 권장한다.

위 코드에 try/catch/finally 구문을 적용해보자.

public void deleteAll() throws SQLException {
    Connection c = null;
    PreparedStatement ps = null;

    try {
        c = this.dataSource.getConnection();

        ps = c.prepareStatement("delete from users");

        ps.executeUpdate();
    } catch (SQLException e) {
        throw e;
    } finally {
        if (ps != null) {
            try {
                ps.close();
                // ps.close 에서도 예외처리를 해주는 이유
                // SQLException이 발생할 수 있기 때문에 이를 잡아줘야 한다.
                // 그렇지 않으면 Connection 을 close()하지 못하고 메소드를 빠져나갈 수 있다.
            } catch (SQLException e) {
                    
            }
        }

        if (c != null) {
            try {
                c.close();
            } catch (SQLException e) {
		        
            }
        }
    }
}

JDBC 조회 기능의 예외처리
조회를 위한 JDBC 코드는 좀 더 복잡해진다.

  • Connection, PreparedStatement 외에도 ResultSet이 추가되기 때문이다.

JDBC 예외처리를 적용한 getCount 메소드

public int getCount() throws SQLException {
	Connection c = null;
    PreparedStatement ps = null;
    ResultSet rs = null;

	try {
    	c = this.dataSource.getConnection();

		ps = c.prepareStatement("select count(*) from users");

		rs = ps.executeQuery();
        rs.next();

		int count = rs.getInt(1);

		return count;
    } catch (SQLException e) {
    	throw e;
    } finally {
    	if (rs != null) {
        	try {
            	rs.close();
            } catch (SQLException e) {
            
            }
        }

		if (ps != null) {
        	try {
            	ps.close();
            } catch (SQLException e) {
                    
            }
        }

        if (c != null) {
            try {
                c.close();
            } catch (SQLException e) {
                    
            }
        }
    }
}

이제 UserDao의 모든 메소드에 동일한 방식으로 try/catch/finally 블록을 적용했다.
모든 작업을 마쳤으면 UserDaoTest 테스트를 수행해보고 이상이 없는지 확인한다.

profile
https://github.com/yuseogi0218

0개의 댓글