포스트

Day62 실습프로젝트(DB커넥션)

ProxyPattern

MultiTread의 문제점

  • 하나의 SqlSession을 생성하여 하나의 캐시를 공유한다.
  • 하나의 클라이언트에서 커밋을 하면 전체 캐시가 데이터베이스에 업데이트된다.
  • 다른 클라이언트에서 오류가 발생해도 롤백되지 않는다.

image


Factory Pattern

SqlSessionFactory생성

  • SqlSessionFactory를 만들어서 쓰레드당 하나의 SqlSession를 갖게 만든다.
  • 클라이언트가 접속 후 명령을 수행할때 고유의 SqlSession이 있는지 확인 후 할당한다.
  • 그외 다른 기능은 기존의 SqlSession에게 위임한다.

image

별도 SqlSession 할당

  • 각자 고유의 캐시를 가지기 때문에 다른 클라이언트의 작업이 현재 클라이언트의 작업에 영향을 미치지 않는다.

image


코드 수정

SqlSessionFactory 생성

  • GoF의 Proxy 패턴을 적용하여 SqlSessionFactoryProxy 클래스 정의
  • SqlSessionFactory의 openSession(boolean) 메서드의 기능 변경
  • 스레드 별로 같은 SqlSession 객체를 리턴
1
2
3
4
5
6
7
8
9
10
11
12
13
// 나머지는 원래 SqlSessionFactory에 위임을 한다.
 @Override
public SqlSession openSession(boolean autoCommit) {
  SqlSession sqlSession = sqlSessionThreadLocal.get();

  if (sqlSession == null) {
    sqlSession = original.openSession(autoCommit);
  }

  sqlSessionThreadLocal.set(sqlSession);

  return sqlSession;
}


DaoFactory 클래스 변경

  • Dao 구현체에서 작업할 때 SqlSessionFactory를 통해 SqlSession 객체를 얻어 사용하도록 변경
1
2
3
4
5
6
7
8
9
private SqlSessionFactory sqlSessionFactory;

public DaoFactory(SqlSessionFactory sqlSessionFactory) {
  this.sqlSessionFactory = sqlSessionFactory;
}

//중략
//sqlSession을 Factory에서 받아는 코드를 추가한다.
SqlSession sqlSession = sqlSessionFactory.openSession(false);


Command 구현체 변경

  • private SqlSessionFactory sqlSessionFactory;private SqlSessionFactory sqlSessionFactory;으로 변경한다.
  • commit()/rollback()을 수행할 때 SqlSessionFactory를 통해 SqlSession을 얻어 사용하도록 변경
  • sqlSession.commit();sqlSessionFactory.openSession(false).commit();으로 변경한다.
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
public class BoardDeleteCommand implements Command {

  private BoardDao boardDao;
  //sqlSession -> sqlSessionFactory
  private SqlSessionFactory sqlSessionFactory;

  public BoardDeleteCommand(BoardDao boardDao, SqlSessionFactory sqlSessionFactory) {

    this.boardDao = boardDao;
    this.sqlSessionFactory = sqlSessionFactory;
  }

  @Override
  public void execute(String menuName, Prompt prompt) {
   //중략
      boardDao.delete(boardNo);
      sqlSessionFactory.openSession(false).commit();
      prompt.printf("'%s'번 게시글을 삭제 했습니다.\n", deletedBoard.getNo());

    } catch (Exception e) {
      sqlSessionFactory.openSession(false).rollback();
      prompt.println("삭제 중 오류 발생!");
    }
  }
}


이 기사는 저작권자의 CC BY 4.0 라이센스를 따릅니다.