[Springboot] PostConstruct에서 transactional 처리

항상 정리하기·2022년 2월 2일
0
post-custom-banner

RestController 클래스 생성 후 테스트용 데이터를 초기화하는 아래 코드를 추가했다.

    @PostConstruct
    public void initData() {
        Team teamA = new Team("teamA");
        Team teamB = new Team("teamB");

        for (int i = 0; i < 100; i++) {
            Team selectedTeam = i % 2 == 0 ? teamA : teamB;
            em.persist(new Member("member" + i, selectedTeam, i));
        }
    }

그리고 맞이한 에러 메시지...

Caused by: javax.persistence.TransactionRequiredException: No EntityManager with actual transaction available for current thread - cannot reliably process 'persist' call

그래서 찾아본 결과 아래와 같은 해결방법을 찾았다.
https://sorjfkrh5078.tistory.com/311

  • 다른 스프링 빈을 호출해서 사용하는 방법
  • AOP를 사용하지 않고 트랜잭션을 직접 코딩하는 방법
  • 애플리케이션 컨텍스트가 완전히 초기화된 이벤트를 받아서 호출하는 방법
  • 초기화하는 메서드와 초기화를 실행하는 메서드를 분리하는 방법

내가 적용한 방법은 4번째. 다른 스프링 빈을 호출해서 사용하는 방법.

아래와 같은 InitMemberService를 추가하고,

@Component
public class InitMemberService {

    @PersistenceContext
    EntityManager em;

    @Transactional
    public void init() {
        Team teamA = new Team("teamA");
        Team teamB = new Team("teamB");

        em.persist(teamA);
        em.persist(teamB);

        for (int i = 0; i < 100; i++) {
            Team selectedTeam = i % 2 == 0 ? teamA : teamB;
            em.persist(new Member("member" + i, selectedTeam, i));
        }
    }
}

RestController 클래스에서 주입받고 실행하니 정상적으로 처리됐다.

@RestController
public class MemberController {

    @Autowired
    private InitMemberService initMemberService;

    @PostConstruct
    public void initData() {
        initMemberService.init();
    }

참조

profile
늦은 것 같지만 이제부터라도 차근차근 하나씩 정리하기
post-custom-banner

0개의 댓글