- AOP에서 막혀서 다시 시작
- 학습하는 장에서 작업을 시작
- 한 장이 끝난 경우 마스터에서 끝난 장을 머지하고 새로운 장의 브렌치를 만든다
- 공부 기간(2021/1/29 ~ 2021/1/30)
- 3번째 읽는 중^^..
- 기본적인 DB서비스 과정
- DB연결 정보를 제공하여 DB연결
- 쿼리 생성
- 쿼리 수행 및 결과 반환
- DB연결 반환
-
DB연결이 바뀔 때마다 모든 메서드를 수행해야할까? -> DB연결 작업만 메서드로 분리하기
-
결국 클래스의 변경이 일어나는 건 막지 못할까? -> DB연결을 추상메서드로 만들고 상속받아 재구현하기
-
상속이 강제되면 다른 유연함을 포기해야할텐데? -> 다른 클래스에게 DB연결 책임을 위임 private final DataSource dataSource; DataSource는 인터페이스이며 DataSource의 구현체를 통해 초기화해야함
-
DataSource의 초기화를 소유 클래스가 직접한다면? 결국 DataSource의 구현체가 바뀔 때마다 소유클래스 코드 변경
-
생성자를 이용한 초기화 외부에서 구현체를 직접 정한다. 제어의 역전, 의존성 주입 사용
많은 객체를 다루기 위해 아예 생성 전용 클래스를 만든다. -> 스프링컨테이너의 등장배경
결국
- 프로그래머가 스프링컨테이너 조립
- 프로그램 실행
- 스프링컨테이너가 생성할 모든 클래스에 적절한 의존성 주입
의존성이 변경될 때마다 스프링컨테이너만 조작하면 된다. 그 외 다른 코드는 건드릴 필요가 없다.
시나리오에 맞게 assertEqual assertThrow 와 같은 메서드 활용
서비스 시나리오를 모두 테스트로 작성한 뒤 본 서비스를 작성하자
자원을 얻어오는 프로세스는 적절하게 분리 완료한 상태 그렇다면 DB와 연결하는 공통된 프로세스를 다시 분리할 수 없을까?
- DB연결 정보를 제공하여 DB연결
- 쿼리 생성
- 쿼리 수행 및 결과 반환
- DB연결 반환
공통된 작업을 수행하는 틀을 생성하고 원하는 PreparedStatement만 전달하는 구조 PreparedStatement를 직접 상속받아 클래스를 만들어 전달할 수도 있지만 그보다는 익명클래스를 사용해 전달하는 방식 채용
context작업을 클래스의 메서드 수준이 아닌 클래스로 빼서 범용으로 만들어고, context를 사용하려는 클래스는 이 클래스를 주입받자
PreparedStatement는 클라이언트가 만들어서 context 클래스에 전달했다. 맞는건가? 그럼 모든 서비스 메서드는 PreparedStatement를 만드는 코드를 넣어야 한다. 더 나아가 모든 context사용 클래스도 마찬가지다.
결국 PreparedStatement를 만드는 과정도 중복으로 볼 수 있고 클라이언드가 전달해줄 값은 쿼리와 쿼리의 파라미터다. context를 가진 메서드에서 PreparedStatement의 생산 책임도 갖자.
예외처리 추상화의 필요성
- 체크예외는 try catch를 통해 처리하거나 예외가 발생하는 메서드를 호출한 메서드에 throws 예외를 붙이는 처리를 반드시 해야한다.
- 언체크예외는 따로 아무런 처리를 하지 않아도 콜스택으로 예외를 떠넘긴다.
DB별로 jdbc의 구현체가 제각기 다른 예외를 던진다면 이 예외를 catch하기 위한 클라이언트 메서드는 jdbc의 기술에 강하게 결합될 수밖에 없다. 하지만 DB의 예외는 대체로 일관적이다. 어느 DB에서 발생하는 예외의 상황이 대동소이하다. 스프링은 이러한 예외를 추상화한 계층으로 서비스를 제공한다. 스프링의 jdbc사용 유저는 스프링이 추상화한 예외 계층을 catch하면 jdbc의 구현 기술과 독립된 예외처리 코드를 작성할 수 있다.
객체의 고유한 기능을 조합한 서비스로직
- 조건의 만족여부를 결정하는 UpgradePolicy
- 본인의 레벨을 변경하는 Users
- 어떤 레벨로 변경할지를 정하는 Level
- 변경사항을 저장하는 Dao
- 각각의 객체에서 임수를 부여하는 UserService
한 서비스 로직에서 수행될 쿼리가 여러개일 때 몇몇 쿼리가 호출된 후 서비스 로직에 예외가 발생한다면? ->일관된 결과를 보장하지 못함 서비스 로직 단위로 트랜잭션을 묶을 필요성이 생김
- 트랜잭션은 커넥션에 종속적이다.
- 트랜잭션을 서비스 단위로 묶기 위해서 애써 JdbcTemplate으로 뺀 커낵션을 다시 가져와야 함
- 다행히도 전역트랜젝션 관리 라이브러리 사용으로 문제해결(jdbctemplate는 전역트랜젝션이 없을 시에 개별 커넥션 생성)
- 다만, 이러한 트랜잭션 관리는 DataSource기술에 의존적
- 어댑터 패턴을 이용해서 spring이 기술에 독립적인 추상타입 제공