3-19 서비스 계층의 분리와 @Transactional(1)

서현우·2022년 5월 19일
0

스프링의정석

목록 보기
46/85

1. 서비스 계층(Layer)의 분리 - 비지니스 로직의 분리

@Controller - 컨트롤러, Presentation영역
@Repository - Dao, Persistence영역, Data Access Layer(영속 계층)
(중복코드 제거, 관심사의 분리를 위해 나눔.)

@Repository의 메서드를 사용해서, 서비스 계층에서
userDao.insertUser(user) 이렇게 길어지지 않도록
메서드를 저장해놓고, 컨트롤러에서 갖다 쓰기만 하도록 함.

만약 User가 insert될 때, User의 history도 insert 되게 하려면 Tx를 사용해야 함.
Tx를 사용하기 위해서는 서비스 계층을 사용하는 것이 유리.
컨트롤러에 Tx를 쓰면 너무 복잡해짐.

@Controller, @Service, @Repository
셋 다 @Component로 <componenet-scan>이 가능.

2. TransactionManager란?

DAO의 각 메서드는 개별 Connection을 사용.

@Repository
public class UserDaoImpl implements UserDao {
	@Autowired DataSource ds;
	
	public int deleteUser(String id) {
		Connection conn = null;
		PreparedStatement pstmt = null;
		String sql = "delete from user_info where id= ? ";
		
		try{
			conn = ds.getConnection();
			pstmt = conn.prepareStatement(sql);
			pstmt.setString(1, id);
			return pstmt.executeUpdate();
			...

DAO의 각 메서드는 개별 Connection을 사용하는데 n개의 메서드를 하나의 Connection을 사용하게 하기 위해서 Tx를 사용해야 함.

같은 Tx내에서 같은 Connection을 사용할 수 있게 관리.
DAO에서 Connection을 얻거나 반환할 때 DataSourceUtils를 사용해야 함.

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

//아래처럼 변환 시켜야 함.
conn = DataSourceUtils.getConnection(ds);
//...
DataSourceUtils.releaseConnection(conn, ds);

3. TransactionManager로 Transaction 적용하기

//DataSourceTransactionManager(ds) //TxManager 생성
public void inserWithTx() throws Exception {
	PlatformTransactionManager tm = new DataSourceTransactionMangager(ds);
	//DefaultTransactionDefinition //Tx의 속성을 정의
	TransactionStatus status = tm.getTransaction(new DefaultTransactionDefinition());

	//Tx 시작
	try {
		a1Dao.insert(1,100);
		a1Dao.insert(1,200);
		t.commit(status); //Tx 끝 - 성공(커밋)
	} catch(Exception ex) {
		tm.rollback(status); //Tx 끝 - 실패(롤백)
	}
}

빈으로 등록하는 방법

<bean id="transactionManager" class="org.springframework.jdbc.datesource.DataSourceTransactionManager">
	<property name="dataSource" ref="dataSource"/>
</bean>
<tx:annotation-driven/> //@Transactional 사용가능

4. @Transactional로 Transaction 적용하기

AOP를 이용한 핵심 기능과 부가 기능의 분리

public void insertWithTx() throws Exception {
	PlatformTransactionManager tm = new DataSourceTransactionManager(ds);
	TransactionStatus status = tm.getTransaction(new DefaultTransactionDefinition());
	
	try {
		a1Dao.insert(1,100);
		a1Dao.insert(1,200);
		tm.commit(status);
	} catch(Exception ex) {
		tm.rollback(status);
	}
}

==> 핵심 기능 분리

@Transactional
public void insertWithTx() throws Exception {
	a1Dao.insert(1,100);
	a1Dao.insert(1,200);
} //핵심 로직만 집중 가능

@Transactional은 클래스나 인터페이스에도 붙일 수 있음.

  • 클래에 붙이면 클래스 내의 모든 메서드에 적용.
  • 인터페이스에 붙이면, 인터페이스를 구현하는 클래스의 모든 메서드에 적용.
profile
안녕하세요!!

0개의 댓글