기존 CRUD에 정해진 조건에 따라 사용자의 레벨을 주기적으로 변경하는 비즈니스 로직 추가

ENUM 사용하기

private enum level {
	 BASIC(1), SILVER(2), GOLD(3);
}
  • 내부에는 DB에 저장할 int 타입이지만 겉으로는 level 타입의 오브젝트로 안전한 사용 가능

객체지향적인 코드는 다른 오브젝트의 데이터를 가져와서 작업하는 대신 데이터를 가진 다른 오브젝트에게 작업을 해달라고 요청한다.

트랜잭션 문제

두 가지 작업이 하나의 트랜잭션이 되려면 두 번째 SQL이 성공적으로 DB에서 수행되기 전에 문제가 발생할 경우 앞에서 처리한 SQL 작업도 취소되어야 함 트랜잭션 롤백

여러개의 SQL을 하나의 트랜잭션으로 처리하는 경우 성공적으로 마무리 됐다고 DB에 알려줘서 확정시키는 것 트랜잭션 커밋

트랜잭션 경계설정

Connection c = dataSource.getConnection();
 
c.setAutoCommit(false); // 트랜잭션 시작
try {
	~~~~~~~~~~
	c.commit(); // 트랜잭션 커밋
}
catch(Exception e) {
	c.rollback(); // 트랜잭션 롤백
}
  • setAutoCommit(false)로 트랜잭션의 시작을 선언하고 commit() / rollback()으로 트랜잭션을 종료하는 작업
  • 트랜잭션의 경계는 하나의 Connection이 만들어지고 닫히는 범위 내에 존재

작업들이 하나의 트랜잭션으로 묶이려면 그 작업이 진행되는 동안 DB 커넥션도 하나만 사용돼야 함

@Transactional...?

트랜잭션 동기화

트랜잭션을 시작하기 위해 만든 Connection 오브젝트를 특별한 저장소에 보관해두고, 이후에 호출되는 DAO의 메소드에서는 저장된 Connection을 가져다가 사용하게 하는 것

트랜잭션 서비스 추상화

글로벌 트랜잭션 방식을 사용해야 할 경우 JTA

JTA를 사용하면 여러 개의 DB나 메시징 서버에 대한 작업을 하나의 트랜잭션으로 통합하는 분산 트랜잭션 / 글로벌 트랜잭션 가능

Hibernate를 이용한 트랜잭션 관리 코드는 JDBC나 JTA와는 달라서 다시 특정 데이터 액세스에 종속됨

특정 트랜잭션 방법에 의존하지 않고 독립적이게 만드려면? 추상화

서비스 추상화와 단일 책임 원칙

수직, 수평 계층구조와 의존관계

애플리케이션 로직의 종류에 따라 수평적인 구분이든, 로직과 기술이라는 수직적인 구분이든 모두 결합도가 낮음 서로 영향을 주지않고 확장 가능한 구조를 만드는데 DI가 중요한 역할을 함 DI는 관심, 책임, 성격이 다른 코드를 깔끔하게 분리 할 수 있게 함

단일 책임 원칙 (SRP)

하나의 모듈은 한 가지 책임을 가져야 한다는 의미 어떤 변경이 필요할 때 수정 대상이 명확해짐

이를 위한 핵심적인 도구는 바로 DI~ 암튼 DI 가 제일 중요~

테스트 대역(test double)

테스트 대상이 의존하는 요인 때문에 테스트가 어려울 때 테스트 대역 사용

테스트 스텁

테스트 대상 오브젝트의 의존객체로서 존재하면서 테스트 동안 코드가 정상적으로 수행할 수 있도록 도움 테스트가 수행될 수 있도록 의존 오브젝트에 간접적으로 입력값을 제공

목 오브젝트

테스트 대상의 간접적인 출력 결과를 검증하고 테스트 대상 오브젝트와 의존 오브젝트 사이에 일어나는 일을 검증할 수 있도록 설계 스텁의 역할 + 간접적인 출력값까지 확인 가능

이일민, [토비의 스프링 3.1], 에이콘 출판사(2012)