LUMI_dev

SpringBoot JPA_#1-2. SpringBoot 환경에서의 JPA_트랜잭션 쉽게 적용하는 법 (@Transactional) / EntityManager 쉽게 사용하는 법 (@PersistenceContext) 본문

스파르타 코딩 클럽 | 자바 심화 과정/Spring Master (입문 주차)

SpringBoot JPA_#1-2. SpringBoot 환경에서의 JPA_트랜잭션 쉽게 적용하는 법 (@Transactional) / EntityManager 쉽게 사용하는 법 (@PersistenceContext)

luminous_dev 2025. 2. 4. 01:51


트랜잭션 쉽게 적용하는 법

더보기

JPA는 데이터베이스의 트랜잭션 개념을 가져와서 사용하고 있음 

Springboot에서도 트랜잭션을 JPA에 부여해야 함 

 

Boot에서는 Entity 매니저가 제공하는 Entity 트랜잭션을 사용하는게 아닌

트랜잭션 환경을 손쉽게 만들 수 있음


shift 두 번 누르기 (검색창)  > SimpleJPARepository 검색 > class 클릭해서 선택

 

그럼 창이 뜨는데 > 해당 창에서 save 검색해보기

@Transactional을 클래스나 메서드에 추가하기

@Transactional 클래스/ 메서드 적용

  • 메서드에 호출된 @Transactional
    • 메서드가 호출되면 해당 메서드 내에서 수행되는 모든 DB 연산 내용은 하나의 트랜잭션으로 묶임
    • 해당 메서드가 정상적으로 수행되면 트랜잭션 커밋 / 예외 발생하면 롤백 
  • 클래스에 호출된 @Transactional
    • 클래스 내부의 모든 메서드에 트랜잭션 기능 부여
    • 만약 메서드에도 @Transactional이 추가되어 있으면,
      클래스에 걸린 @Transactional( readOnly = true 옵션) 은 메서드에 적용되지 않음 → readOnly = false 옵션으로 적용
readOnly = true 옵션

트랜잭션에서 '데이터를 읽기만 할 때 사용'
읽기 작업에 대한 최적화를 수행할 수 있음
BUT! 해당 트랜잭션에서 데이터를 수정하려고 하면 예외가 발생함

(*Select할 때 트랜잭션은 필수가 아니지만 쓸 상황이 있음 (그건 나중에))

 


SpringBoot에서 자동으로 생성해주는 EntityManger 사용하는 법

 = @PersistenceContext

public class TransactionTest {
    @PersistenceContext
    EntityManager em;
}

실습) 트랜잭션 테스트 

 

 

트랜잭션 테스트 : 메모 생성 성공 

import org.springframework.transaction.annotation.Transactional;

 

package com.sparta.sparta_memo_project;

import com.sparta.sparta_memo_project.entity.Memo;
import jakarta.persistence.EntityManager;
import jakarta.persistence.PersistenceContext;
import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Test;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.annotation.Rollback;
import org.springframework.transaction.annotation.Transactional;

@SpringBootTest
public class TransactionTest {
    @PersistenceContext
    EntityManager em;
    @Test
    @Transactional
    @Rollback(value = false) // 테스트 코드에서 @Transactional 를 사용하면 테스트가 완료된 후 롤백하기 때문에 false 옵션 추가
    @DisplayName("메모 생성 성공")
    void test1() {
        Memo memo = new Memo();
        memo.setUsername("Robbert");
        memo.setContents("@Transactional 테스트 중!");

        em.persist(memo);  // 영속성 컨텍스트에 메모 Entity 객체를 저장합니다.
    }
}
  • @SpringBootTest를 추가해줘야 함 (이후 강의에서 나옴)
  • 만약 에러가 나면 이미 있는 pk값을 넣어서 그런 걸수도 있음 > 테이블 지웠다가 다시 실행시켜보기
  • @Rollback(value = false)
    : 테스트 코드에서 트랜잭션을 사용하면 테스트가 끝난 후 RollBack을 시키기 때문에
     진짜 저장되는 거 볼거면 false로 설정하기 

 

트랜잭션 테스트 : 메모 생성 실패  

package com.sparta.sparta_memo_project;

import com.sparta.sparta_memo_project.entity.Memo;
import jakarta.persistence.EntityManager;
import jakarta.persistence.PersistenceContext;
import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Test;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.annotation.Rollback;
import org.springframework.transaction.annotation.Transactional;

@SpringBootTest
public class TransactionTest {
    @PersistenceContext
    EntityManager em;
    @Test
    @Transactional
    @Rollback(value = false) // 테스트 코드에서 @Transactional 를 사용하면 테스트가 완료된 후 롤백하기 때문에 false 옵션 추가
    @DisplayName("메모 생성 성공")
    void test1() {
        Memo memo = new Memo();
        memo.setUsername("Robbert");
        memo.setContents("@Transactional 테스트 중!");

        em.persist(memo);  // 영속성 컨텍스트에 메모 Entity 객체를 저장합니다.
    }

    @Test
    @DisplayName("메모 생성 실패")
    void test2() {
        Memo memo = new Memo();
        memo.setUsername("Robbie");
        memo.setContents("@Transactional 테스트 중!");

        em.persist(memo);  // 영속성 컨텍스트에 메모 Entity 객체를 저장합니다.
    }
}

 

test 2 코드에는 트랜잭션이 걸려있지 않은 상황임 

지금 thread에서는 트랜잭션 사용할 수 없음 > 그래서 EntityManger 없음 > persist call 할 수 없음

 

원인) 데이터를 수정할 때는 무조건 트랜잭션 환경이 필요함