@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>
이 가능.
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);
//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 사용가능
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);
} //핵심 로직만 집중 가능