본문 바로가기
Back-end/Spring Framework

spring framework 트랜잭션, @Transactional 처리

by javapp 자바앱 2022. 5. 9.
728x90

 

트랜잭션

트랜잭션은 두 개 이상의 쿼리를 한 작업으로 실행해야할 때 사용합니다.

	@Override
	@Transactional // db 동시에
	public void insert(CommentDTO comment) {
		// 댓글 추가
		mapper.insert(comment);
		// 댓글 수 증감
		bmapper.updateReplyCnt(comment.getBnum(), 1);
	}

이와 같은 메소드를 처리하기 위해 어떻게 해야 될까요?

 

 

 

root-context.xml

Check Namespaces

tx를 체크해줍니다.

	<!--  트랜잭션 -->
	<tx:annotation-driven/>	
	
	<!-- 	TransactionManager  에러 처리-->
	<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
		<property name="dataSource" ref="dataSource" />
	</bean>

<tx:annotation-driven/> 으로 트랜잭션 동작을 활성화시킵니다.

 

DataSourceTransactionManager : JDBC 및 mybatis 등의 JDBC 기반 라이브러리로 데이터베이스에 접근하는 경우에 이용합니다.

 

 

 

 

 

CommentServiceImpl.java

@Service
public class CommentServiceImpl implements CommentService{
	@Autowired
	CommentMapper cmapper;
	@Autowired
	BoardMapper bmapper;
	
	@Override
	@Transactional // db 동시에
	public void insert(CommentDTO comment) {
		// 댓글 추가
		cmapper.insert(comment);
		// 댓글 수 증감
		bmapper.updateReplyCnt(comment.getBnum(), 1);
	}

@Transactional // 어노테이션을 통해 트랜잭션 처리

mybatis를 통해 mapper 객체를 이용하여 DB 접근합니다.

 

 

 

mapper.java

public interface CommentMapper 
{
	public void insert(CommentDTO comment);
    ,,,
public interface BoardMapper 
{
	public void updateReplyCnt(@Param("bnum")int num, @Param("amount")int mount);  // xml 에서 사용할 수 있도록 hashmap 형태로 만든다.
	...

 

 

 

CommentMapper.xml

<mapper namespace="com.board.mapper.CommentMapper">
  	<insert id="insert">
 		insert into commentboard(userid, content,regdate,bnum) values(#{userid}, #{content},now(), #{bnum})
 	</insert>
</mapper>

BoardMapper.xml

 <mapper namespace="com.board.mapper.BoardMapper">
  	<update id="updateReplyCnt">
 		update board set replaycnt= replaycnt+ #{amount}
 		where num=#{bnum}
 	</update>
 </mapper>

 

 

 

 


 

 

 

삭제하기(Delete)

@Service 단에서 @Transactional 처리

//JPA의 엔티티가 영속성 컨텍스트를 통해 관리되면 1차 캐시, 변경 감지(더티 체킹) 등 가지는 이점이 많다.
//하지만 영속성 컨텍스트는 변경 감지를 위해 스냅샷 인스턴스를 보관하기 때문에 더 많은 메모리를 사용하게 된다.
//단순 조회의 수가 많아질수록 더 많은 메모리가 낭비되기 때문에 최적화해줄 필요가 있다.
// 메모리 최적화 (스냅샷 보관 X)
@Transactional(readOnly = true) 
@Service
public class BoardService 
{
	@Autowired
	BoardRepository boardRepository;
	
	@Transactional // 2개의 트랜잭션 처리 도중 에러가 났을때 자동 rollback 위함
	public void insert(Board board, User user) {
		board.setUser(user);
		boardRepository.save(board);
		
	}


	public List<Board> findAll() {
		return boardRepository.findAll();
	}


	public Long count() {

		return boardRepository.count();
	}


	public Board findById(Long num) {
		return boardRepository.findById(num).get();
	}

	@Transactional // 2개의 트랜잭션 처리 도중 에러가 났을때 자동 rollback 위함, 바로 DB 반영
	public void delete(Long num) {
		boardRepository.deleteByNum(num);
	}

}

JPA의 엔티티가 영속성 컨텍스트를 통해 관리되면 1차 캐시, 변경 감지(더티 체킹) 등 가지는 이점이 많습니다.
하지만 영속성 컨텍스트는 변경 감지를 위해 스냅샷 인스턴스를 보관하기 때문에 더 많은 메모리를 사용하게 된니다.
단순 조회의 수가 많아질수록 더 많은 메모리가 낭비되기 때문에 최적화해줄 필요가 있니다.
메모리 최적화 (스냅샷 보관 X)

 

* 2개의 트랜잭션 처리 도중 에러가 났을때 자동 rollback 위함, 

수정, 삭제의 경우 바로 DB 반영

 

@Repository
public interface BoardRepository extends JpaRepository<Board, Long>
{
	void deleteByNum(Long num);
}

 

 

수정 하기(Update)

	// 수정하기 --> 더티 체킹
	// 영속성 컨텍스트에 있는 객체 (Board) 먼저 구하고 set
	@Transactional
	public void update(Board board) {
		Board b = boardRepository.findById(board.getNum()).get();
		b.setTitle(board.getTitle());
		b.setContent(board.getContent());
		
	}
Hibernate: select board0_.num as num1_0_0_, board0_.content as content2_0_0_, board0_.hitcount as hitcount3_0_0_, board0_.regdate as regdate4_0_0_, board0_.replycnt as replycnt5_0_0_, board0_.title as title6_0_0_, board0_.id as id8_0_0_, board0_.writer as writer7_0_0_ from tbl_board4 board0_ where board0_.num=?
Hibernate: update tbl_board4 set content=?, hitcount=?, regdate=?, replycnt=?, title=?, id=?, writer=? where num=?

 

 


 

 

@Transactional

propagation 흔히 쓰는 3개 정리

· REQUIRED (default) : 이미 시작된 트랜잭션이 있으면 참여하고 없으면 새로 시작합니다.

· REQUIRES_NEW : 항상 새로운 트랜잭션을 시작한다. 부모와 자식 중 문제가 생기지 않으면 커밋, 문제 생기면 롤백

· SUPPORTS : 이미 시작된 트랜잭션이 있으면 참여하고, 없으면 트랜잭션없이 진행합니다.

 

조회 메소드 같은 경우는 propagation="SUPPORTS" 와 read-only="true" 를 넣어서 트랜잭션을 태우는게 성능적으로 유리하다고합니다.

 

@Transactional(propagation=Propagation.REQUIRES_NEW, rollbackFor=Exception.classs)

 

 

    @Override
    @Transactional
    public OrderResponse placeOrder(OrderRequest orderRequest) {
        // get order
        Order order = orderRequest.getOrder();

        // set status : inprogress
        order.setStatus("INPROGRESS");
        // set 주문 번호
        order.setOrderTackingNumber(UUID.randomUUID().toString());
        // save
        orderRepository.save(order);


        Payment payment= orderRequest.getPayment();
        // 결제 실패시 예외 처리
        if(!payment.getType().equals("DEBIT")){
            throw new PaymentException("Payment card type do not support");
        }
        // payment set order id
        payment.setOrderId(order.getId());
        // payment 저장
        paymentRepository.save(payment);

        OrderResponse orderResponse = new OrderResponse();
        orderResponse.setOrderTackingNumber(order.getOrderTackingNumber());
        orderResponse.setStatus(order.getStatus());
        orderResponse.setMessage("SUCCESS");
        return orderResponse;
    }

 orderRepository.save(order); 이후 강제 예외를 발생 시켰습니다.

@Transactional 이 없을 경우  orderRepository.save(order); 으로 인해

orders 테이블에 값이 삽입 되었습니다.

 

post man

 

Database 결과

orders table
payments table

 

 

https://oingdaddy.tistory.com/28

 

Spring Transaction Propagation을 예제를 통해 알아보자

spring에서 transaction propagation 은 전파옵션을 뜻한다. 전파옵션이라는 것은 트랜잭션을 시작하거나 기존 트랜잭션에 참여하는 방법에 대해 결정하는 속성값 정도로 생각하면 된다. 즉 큰 트랜잭션

oingdaddy.tistory.com

https://devocean.sk.com/blog/techBoardDetail.do?ID=163799 

 

면접 셤? 단골문제 JPA Propagation과 Isolation 이해하기

 

devocean.sk.com

  • propagation 은 로직 처리를 수행할때 트랜잭션이 어떻게 수행되어야할지에 대한 설정이다. 이 설정을 통해서 트랜잭션을 필요에 따라 구분되어 사용할 수 있게 된다.
  • isolation level은 DBMS 데이터에 대해서 동시성 처리가 일어날때 어떠한 전략을 사용할지 레벨을 설정하는 것이며, 다른 트랜잭션 하에서 데이터를 읽을때 어떻게 데이터가 보이는지에 대한 설정이다.

 

 

 

댓글