public void deleteAll() throws SQLException{
Connection c = null;
PreparedStatement ps = null;
try {
c = dataSource.getConnection();
ps = makeStatement(c);
ps.executeUpdate();
}catch(SQLException e) {
throw e;
}finally {
if (ps != null) {try {ps.close();} catch(SQLException e) {} }
if (c != null) {try {c.close();} catch(SQLException e) {} }
}
}
private PreparedStatement makeStatement(Connection c) throws SQLException{
PreparedStatement ps;
ps = c.prepareStatement("delete from users");
return ps;
}
public abstract class UserDao { //추상 클래스로 변경
//추상 메소드
abstract protected PreparedStatement makeStatement(Connection c) throws SQLException;
public void deleteAll() throws SQLException{
Connection c = null;
PreparedStatement ps = null;
try {
c = dataSource.getConnection();
ps = makeStatement(c);
ps.executeUpdate();
}catch(SQLException e) {
throw e;
}finally {
if (ps != null) {try {ps.close();} catch(SQLException e) {} }
if (c != null) {try {c.close();} catch(SQLException e) {} }
}
}
}
//상속하는 서브 클래스
public class UserDaoDeleteAll extends UserDao{
@Override
protected PreparedStatement makeStatement(Connection c) throws SQLException {
// TODO Auto-generated method stub
PreparedStatement ps = c.prepareStatement("delete * from users");
return ps;
}
}
public class UserDao {
public void deleteAll() throws SQLException{
StatementStrategy st = new DeleteAllStatement(); //선정한 전략 클래스의 오브젝트 생성
jdbcContextWithStatementStrategy(st); //컨텍스트 호출. 전략 오브젝트 전달
}
public void jdbcContextWithStatementStrategy(StatementStrategy stmt) throws SQLException{
Connection c = null;
PreparedStatement ps = null;
try {
c = dataSource.getConnection();
ps = stmt.makePreparedStatement(c);
ps.executeUpdate();
}catch(SQLException e) {
throw e;
}finally {
if (ps != null) {try {ps.close();} catch(SQLException e) {} }
if (c != null) {try {c.close();} catch(SQLException e) {} }
}
}
}
public interface StatementStrategy {
PreparedStatement makePreparedStatement(Connection c) throws SQLException;
}
public class DeleteAllStatement implements StatementStrategy{
@Override
public PreparedStatement makePreparedStatement(Connection c) throws SQLException {
// TODO Auto-generated method stub
PreparedStatement ps = c.prepareStatement("delete from users");
return ps;
}
}
전략 패턴 또한 DAO 메소드마다 새로운 StatementStrategy 구현 클래스(ex. DeleteAllStatement)를 만들어야 하며, User와 같은 부가적인 정보를 전달해야 하는 경우 생성자와 인스턴스 변수를 만들어야 하는 단점이 있음.
로컬 클래스
public void add(final User user) throws ClassNotFoundException, SQLException{
class AddStatement implements StatementStrategy{
@Override
public PreparedStatement makePreparedStatement(Connection c) throws SQLException {
// TODO Auto-generated method stub
PreparedStatement ps = c.prepareStatement("insert into users(id, name, password) values(?,?,?)");
ps.setString(1, user.getId());
ps.setString(2, user.getName());
ps.setString(3, user.getPassword());
return ps;
}
}
StatementStrategy st = new AddStatement(); //User 오브젝트 전달 불필요
jdbcContextWithStatementStrategy(st);
}
익명 내부 클래스 적용
익명 내부 클래스는 선언과 동시에 오브젝트를 생성. 클래스 이름 생략.
클래스를 재사용할 필요 없을 때 사용
public void add(final User user) throws ClassNotFoundException, SQLException{
jdbcContextWithStatementStrategy(new StatementStrategy() {
@Override
public PreparedStatement makePreparedStatement(Connection c) throws SQLException {
// TODO Auto-generated method stub
PreparedStatement ps = c.prepareStatement("insert into users(id, name, password) values(?,?,?)");
ps.setString(1, user.getId());
ps.setString(2, user.getName());
ps.setString(3, user.getPassword());
return ps;
}
});
}
JDBC의 일반적인 작업 흐름을 담고 있는 jdbcContextWithStatementStrategy() 분리. 모든 DAO가 사용할 수 있게끔.
public class JdbcContext { //다른 DAO에서도 사용 가능하다
private DataSource dataSource;
public void setDataSource(DataSource dataSource) {
this.dataSource = dataSource;
}
public void workWithStatementStrategy(StatementStrategy stmt) throws SQLException{
Connection c = null;
PreparedStatement ps = null;
try {
c = this.dataSource.getConection();
ps = stmt.makePreparedStatement(c);
ps.executeUpdate();
}catch(SQLException e) {
throw e;
}finally {
if(ps!=null) {try {ps.close();} catch(SQLException e) {}}
if(c!=null) {try {c.close();} catch(SQLException e) {}}
}
}
}
public class UserDao {
private DataSource dataSource;
// private ConnectionMaker connectionMaker; //초기에 설정하면 사용 중에는 바뀌지 않는 읽기전용 인스턴스
// 변수
public void setDataSource(DataSource dataSource) {
this.dataSource = dataSource;
}
private JdbcContext jdbcContext;
public void setJdbcContext(JdbcContext jdbcContext) {
this.jdbcContext = jdbcContext;
}
public void deleteAll() throws SQLException {
this.jdbcContext.workWithStatementStrategy(new StatementStrategy() {
@Override
public PreparedStatement makePreparedStatement(Connection c) throws SQLException {
return c.prepareStatement("delete from users");
}
});
}
public void add(final User user) throws ClassNotFoundException, SQLException {
this.jdbcContext.workWithStatementStrategy(new StatementStrategy() {
@Override
public PreparedStatement makePreparedStatement(Connection c) throws SQLException {
// TODO Auto-generated method stub
PreparedStatement ps = c.prepareStatement("insert into users(id, name, password) values(?,?,?)");
ps.setString(1, user.getId());
ps.setString(2, user.getName());
ps.setString(3, user.getPassword());
return ps;
}
});
}