메서드 호출할 때마다 Connection 생성
⇒ 메모리 낭비
실제로 Connection 객체를 공유하는 경우로 테스트 했을 경우와 Connection 객체를 공유하지 않고 사용할 때마다 생성하는 경우로 테스트를 했을 때,
공유하는 경우의 속도가 빠른 것을 확인할 수 있었다.
Connection 객체 공유하는 방법
MariaDBMemberDao class
public class MariaDBMemberDao {
Connection con;
public MariaDBMemberDao() throws Exception{
con = DriverManager.getConnection(
"jdbc:mariadb://localhost:3306/studydb", "study", "1111");
}
.
.
.
의존 객체 주입(injection) 방식으로 Connection 객체를 공유하기
Dao가 10개 있다면 모든 DAO마다 Connection 객체가 생성된다.
⇒ 하나의 DBMS에 10개의 Connection 객체가 생성된 후 연결된다.
→ 좋지 않다.
의존 객체: Dependency
public static void main(String[] args) {
try (
// DAO가 사용할 커넥션 객체 준비
Connection con = DriverManager.getConnection(
"jdbc:mariadb://localhost:3306/studydb", "study", "1111");
)
{
System.out.println("[게시글 관리 클라이언트]");
welcome();
// 핸들러를 담을 컬렉션을 준비한다.
ArrayList<Handler> handlers = new ArrayList<>();
handlers.add(new BoardHandler(con));
handlers.add(new MemberHandler(con));
.
.
.
생성자에 connection 객체를 받아오고 그 connection 객체를 공유한다.
com.bitcamp.board.dao.MariaDBMemberDao class 변경
com.bitcamp.board.dao.MariaDBBoardDao class 변경
MariaDBMemberDao class
public class MariaDBBoardDao {
Connection con;
// DAO가 사용할 의존 객체 Connection을 생성자의 파라미터로 받는다.
// 의존객체: 이 객체가 작업하는데 사용하는 것.
public MariaDBBoardDao(Connection con) throws Exception {
this.con = con;
}
....
생성자에 connection 객체를 받아오고 그 connection 객체를 공유한다.
Handler에서 DAO 객체를 교체하기 쉽게 만들기
com.bitcamp.board.dao.MariaDBMemberDao class 변경
com.bitcamp.board.dao.MariaDBBoardDao class 변경
com.bitcamp.board.clientApp 클래스 변경
MariaDBMemberDao class
private MariaDBBoardDao boardDao;
public BoardHandler(MariaDBBoardDao boardDao) throws Exception{
super(new String[] {"목록", "상세보기", "등록", "삭제", "변경"});
this.boardDao = boardDao;
}
...
com.bitcamp.board.dao.MemberDao 인터페이스 정의
com.bitcamp.board.dao.MariaDBMemberDao 클래스 변경
com.bitcamp.board.dao.BoardDao 인터페이스 정의
com.bitcamp.board.dao.MariaDBBoardDao 클래스 변경
MemberDao interface
dbms에 따라 dao를 수정해야하므로 dao의 메서드 호출에 대한 규칙을 인터페이스라는 문법으로 정의하자.
public interface MemberDao {
int insert(Member member)throws Exception;
int update(Member member) throws Exception;
Member findByNo(int no) throws Exception;
int delete(int no) throws Exception;
List<Member> findAll() throws Exception;
}
public class MariaDBMemberDao implements MemberDao{
...
}
인터페이스를 정의하면, 클래스를 제작하는 개발자가 자기마음대로 코드를 변경할 수 없고 규칙에 따라 만들어야 한다.
⇒ 객체를 다른 걸로 교체하기가 쉽다. 유지보수가 쉽다. ← 기존 코드의 변경이 최소화되기 때문이다.
DBMS에 상관없이 MemberDao 규칙을 따르는 DAO을 사용하겠다!
→ MariaDBMemberDao클래스가 MemberDao 인터페이스의 구현체이므로 데이터타입을 MemberDao로 선언할 수 있다.
public static void main(String[] args) {
...
// DAO 객체를 준비한다.
MariaDBMemberDao memberDao = new MariaDBMemberDao(con);
MariaDBBoardDao boardDao = new MariaDBBoardDao(con);
// 핸들러를 담을 컬렉션을 준비한다.
ArrayList<Handler> handlers = new ArrayList<>();
handlers.add(new BoardHandler(boardDao));
handlers.add(new MemberHandler(memberDao));
public class MemberHandler extends AbstractHandler{
// DBMS에 상관없이 MemberDao 규칙을 따르는 DAO을 사용하겠다!
private MemberDao memberDao;
public MemberHandler(MemberDao memberDao) throws Exception{
....
여러 개의 데이터 변경 작업을 한 단위로 묶는 방법
com.bitcamp.board.dao.MariaDBMemberDao class 변경
MariaDBMemberDao class
public int delete(int no) throws Exception{
try(
PreparedStatement pstmt1 = con.prepareStatement( "delete from app_board where mno = ?"); // 자식 데이터 지우기
PreparedStatement pstmt2 = con.prepareStatement( "delete from app_member2 where mno = ?") // 부모 데이터 지우기
) //try ()
{
// 커넥션 객체를 수동 커밋 상태로 설정한다.
con.setAutoCommit(false);
// 자식 데이터 지우기 - 회원이 작성한 게시글 삭제
pstmt1.setInt(1, no);
pstmt1.executeUpdate();
// 부모 데이터 지우기 - 회원 데이터 삭제
pstmt2.setInt(1, no);
int count = pstmt2.executeUpdate();
// 현재까지 작업한 데이터 변경 결과를 실제 테이블에 적용해 달라고 요청한다.
con.commit();
return count;
} /*try() {}*/catch(Exception e) {
// 예외가 발생하면 마지막 커밋 상태로 돌린다.
// => 임시 데이터베이스에 보관된 이전 작업 결과를 모두 취소한다.
con.rollback();
// 예외 발생 사실을 호출자에게 전달한다.
throw e;
}finally {
// 삭제 작업 후 자동 커밋 상태로 전환한다.
con.setAutoCommit(true);
}
}
프로젝트 생성
↓
구현
↕
테스트
↕
리뷰
클라우드 서버 준비
↓
설정
↓
실행