티스토리 뷰
스프링과 비교되는 EJB는 모든 비즈니스 메소드에 대한 트랜잭션 관리를 EJB 컨테이너가 자동으로 처리해준다. 스프링에서도 EJB와 마찬가지로 트랜잭션 처리를 컨테이너가 자동으로 처리하도록 설정할 수 있는데, 이를 선언적 트랜잭션 처리라고 한다.
1. 트랜잭션 네임스페이스 등록
- applicationContext.xml의 namespace탭에서 tx를 선택한다.
2. 트랜잭션 관리자 등록
- 어떤 기술을 이용하여 데이터베이스 연동을 처리했느냐에 따라 트랜잭션 관리자가 달라진다.
- 모든 트랜잭션 관리자는 PlatformTransactionManager 인터페이스를 구현한 클래스들이다.
1 2 3 4 5 6 | public interface PlatformTransactionManager { TransactionStatus getTransaction(TransactionDefinition definition) throws TransactionException; void commit(TransactionStatus status) throws TransactionException; void rollback(TransactionStatus status) throws TransactionException; } | cs |
3. applicationContext.xml 설정
3-1. DataSourceTransactionManager 클래스 <bean> 등록
- DataSourceTransactionManager를 <bean> 등록했다고 자동으로 트랜잭션이 관리되지 않는다.
- DataSourceTransactionManager의 commit(), rollback()를 재정의하여 구현했을 뿐이기 때문에 PlatformTransactionManager 객체 스스로 자신이 가진 메소드를 실행할 수 없다.
- 어드바이스를 이용하여 예외 처리와 트랜잭션을 처리한다.
3-2. 트랜잭션 어드바이스 설정
- 지금까진 AOP 관련 설정에 사용한 모든 어드바이스 클래스를 직접 구현했지만, 트랜잭션 관리 기능의 어드바이스는 직접 구현하지 않으며, 스프링 컨테이너가 <tx:advice>를 참조하여 자동으로 생성한다.
> 트랜잭션 관리 어드바이스 객체에 클래스 이름이나 메소드를 확인할 수 없다는 의미이기도 하다.
- get으로 시작하는 모든 메소드는 일기 전용으로 처리하여 트랜잭션 관리 대상에서 제외하고 나머지 메소드들은 트랜잭션에 포함한다.
3-3. AOP 설정을 통한 트랜잭션 적용
- <tx:advice>를 통해 직접 클래스를 구현하지 않고 스프링 컨테이너가 자동으로 생성하므로 어드바이스 메소드 이름을 알 수 없다.
> 어드바이스 메소드 이름을 모르므로 <aop:aspect> 엘리먼트를 사용하지 못하고 <aop:advisor>를 사용한다.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 | <?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:p="http://www.springframework.org/schema/p" xmlns:context="http://www.springframework.org/schema/context" xmlns:aop="http://www.springframework.org/schema/aop" xmlns:tx="http://www.springframework.org/schema/tx" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.2.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-4.2.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-4.2.xsd"> <context:component-scan base-package="com.springbook.biz"></context:component-scan> <aop:aspectj-autoproxy></aop:aspectj-autoproxy> <!-- DataSource 설정 --> <bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close"> <property name="driverClassName" value="org.h2.Driver" /> <property name="url" value="jdbc:h2:tcp://localhost/~/test" /> <property name="username" value="sa" /> <property name="password" value="" /> </bean> <!-- Spring JDBC 설정 --> <bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate"> <property name="dataSource" ref="dataSource"></property> </bean> <!-- Transaction 설정 --> <bean id="txManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager"> <property name="dataSource" ref="dataSource"></property> </bean> <tx:advice id="txAdvice" transaction-manager="txManager"> <tx:attributes> <tx:method name="get*" read-only="true"/> <tx:method name="*"/> </tx:attributes> </tx:advice> <aop:config> <aop:pointcut expression="execution(* com.springbook.biz..*(..))" id="txPointcut"/> <aop:advisor pointcut-ref="txPointcut" advice-ref="txAdvice"/> </aop:config> </beans> | cs |
4. 트랜잭션 설정 테스트
- 고의로 예외사항을 만들기 위해 insert를 같은 seq로 두번하도록 설정한다.
> 트랜잭션은 메소드 단위로 관리된다.
- seq를 100으로 설정한다.
> 실행 시 DuplicateKeyException에러가 발생한다.
- 29라인을 주석 처리 후 실행하면 클이 등록되지 않은것을 확인 할 수 있다.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 | // BoardServiceImpl.java public void insertBoard(BoardVO vo) { boardDAO.insertBoard(vo); boardDAO.insertBoard(vo); } // BoardDAOSpring.java private final String BOARD_INSERT = "insert into board(seq, title, writer, content) values(?,?,?,?)"; // ~~~ // CRUD 기능의 메소드 구현 // 글 등록 public void insertBoard(BoardVO vo) { System.out.println("===> JDBC로 insertBoard() 기능 처리"); jdbcTemplate.update(BOARD_INSERT, vo.getSeq(), vo.getTitle(), vo.getWriter(), vo.getContent()); } // BoardServiceClient.java // 3. 글 등록 기능 테스트 BoardVO vo = new BoardVO(); vo.setSeq(100); vo.setTitle("임시 제목"); vo.setWriter("홍길동"); vo.setContent("임시 내용17"); boardService.insertBoard(vo); | cs |
'spring' 카테고리의 다른 글
day3 class03 Model2 아키텍처로 게시판 개발 (0) | 2019.01.20 |
---|---|
day3 class01~02 model1 아키텍처로 게시판 개발 (0) | 2019.01.16 |
day2 class06 스프링 JDBC (0) | 2019.01.13 |
day2 class05 어노테이션 기반 AOP (0) | 2019.01.06 |
day2 class04 JoinPoint와 바인드 변수 (0) | 2019.01.06 |
- Total
- Today
- Yesterday
- 횡단 관심
- 스프링 컨테이너
- aspect oriented programming
- afterCompletion
- handlermapping
- preHandler
- postHandler
- NoClassDefFoundError
- 의존성 주입
- @Autowired
- application context
- #java.lang.NoClassDefFoundError: org/slf4j/event/LoggingEvent삭제
- ViewResolver
- LoggingEvent
- setter 인젝션
- blocking
- java.lang.NoClassDefFoundError: org/slf4j/event/LoggingEvent
- multiple SLF4J bindings
- 어노테이션
- 의존성
- 검색
- exclude-mapping
- SqlSessionFactoryBean
- 컨트롤러
- servlet context
- aop
- XmlWebApplicationContext
- Class path contains multiple SLF4J bindings
- JoinPoint
- Controller
일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | ||||
4 | 5 | 6 | 7 | 8 | 9 | 10 |
11 | 12 | 13 | 14 | 15 | 16 | 17 |
18 | 19 | 20 | 21 | 22 | 23 | 24 |
25 | 26 | 27 | 28 | 29 | 30 | 31 |