서비스 계층의 분리

정태규·2023년 2월 20일
0

서비스 계층(Layer)의 분리- 비지니스 분리

[출처]: 스프링의 정석

Controller는 단순호출만 하고 UserService(비지니스 로직)에서 여러 정책들을 관리한다. (회원 포인트,회원정보 등등)

  • 각 계층별 필요한 Annotation
    RegisterController- @Controller
    UserService-@Service
    UserDao-@Repository
    위에 있는 Annotation들은 @Component를 포함하고 있어서 componet scan으로 scan이 가능하다.

TransacationManager

UserDao의 각 메서드들은 각각의 connection을 갖는다. 그 의미는 메서드를 호출하고 나면 commit이 되어버린다는 것이다. commit이 되면 rollback을 할 수가 없다.
때문에 하나의 transaction으로 이어져야 하는 것들을 모아서 한번의 관리해주는 것을 TransactionManager라고 한다.

이렇게 하기 위해서는 기존에

conn = ds.getConnection();
//...
try{if(conn)!=null} conn.close();} //반환
catch(SQLException e){e.printStackTrace();}

이렇게 사용하던것을 아래처럼 바꿔줘야 한다.

conn = DataSourceUtils.getConnection(ds);
//...
DataSourceUtils.releaseConnection(conn,ds);

좀더 자세하게 들어가면

public void insertWithTx() throws Exception{
	PlatformTransactionManager tm = new DataSourceTransactionManager(ds);
    TransactionStatus status = tm.getTransaction(new DefaultTransactionDefinition()); // DefaultTransactionDefinition은 Tx의 속성을 정의한다. 일단은 Default값으로
    
    try{
    	a1Dao.insert(1,100);
        a1Dao.insert(1,200);
        tm.commit(status); //Tx끝 -성공(커밋)
    }catch(Exception ex){
    	tm.rollback(status); // Tx끝 - 실패(롤백)
    }
}

TransactionManager가 같은 connection을 사용하게 해준다.

위처럼 직접 등록하지 않고 bean으로 등록하는 방법도 있다.

<bean id ="transactionManger" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
  <property name="dataSource" ref="dataSource"/>
</bean>
<tx:annotation-driven/> // 이게 있어야 @Transactional 사용 가능

위의 코드를 AOP로 바꿔주면 다음과 같다.

@Transactional
public void insertWithTx() throws Exception{
	a1Dao.insert(1,100);
	a1Dao.insert(1,200);
}

@Transactional을 붙여줌으로써 해당 메서드를 실행할때 앞뒤 코드가 같이 실행된다.
만약 @Transactional을 class에 붙인다면, 해당 class안에 있는 모든 메서드에서 실행된다. interface도 마찬가지다.

@Transactional의 속성

  • propagation : Tx의 경계를 설정하는 방법을 지정
  • isolation : Tx의 isolation level을 지정, DEFAULT,READ_UNCOMMITTED,READ_COMMITTED,REPEATABLE_READ,SERIALIZABLE
  • readOnly : Tx이 데이터를 읽기만 하는 경우, true로 지정하면 성능이 향상
  • rollbackFor: 지정된 예외가 발생해도,Tx을 rollback하지 않음
  • noRollbackFor: 지정된 예외가 발생해도,Tx을 rollback하지 않음
  • timeout : 지정된 시간(초) 내에 Tx이 종료되지 않으면,Tx를 강제 종료

propagation속성의 값

  • REQUIRED : Tx이 진행중이면 참여하고, 없으면 새로운 Tx시작(디폴트)
  • REQUIRED_NEW : Tx이 진행 중이건 아니건, 새로 Tx시작(Tx안에 다른 Tx)
  • NESTED : Tx이 진행 중이면,Tx의 내부 Tx로 실행(Tx안에 sub Tx)

REQUIRED_NEW와 NESTED를 많이 헷갈리는데, 전자는 서로 아예 다른 Tx이고 후자는 같은 Tx의 sub느낌이다.

  • MANDATORY : 반드시 진행중인 Tx 내에서만 실행가능. 아니면 예외 발생
  • SUPPORTS : Tx이 진행 중이건 아니건 상관없이 진행
  • NOT_SUPPORTED: Tx없이 처리. Tx이 진행중이면 잠시 중단
  • NEVER: Tx 없이 처리.Tx이 진행중이면 예외 발생

0개의 댓글