inblog logo
|
silver
    프로젝트

    [프로젝트] 두 개의 테이블에 동시 Insert 문제

    silver's avatar
    silver
    Dec 07, 2024
    [프로젝트] 두 개의 테이블에 동시 Insert 문제

    문제 상황

    회원가입 시 `user_tb`와 `user_account_tb` 두 테이블에 데이터를 저장해야 하는데, JPQL로는 한 번에 불가능

    처음 작성한 코드

    @Transactional public void 회원가입(UserRequest.JoinDTO joinDTO) { User user = joinDTO.toEntity(passwordEncoder); userRepository.join(user); UserAccount userAccount = joinDTO.toEntity(user); userRepository.join2(userAccount); }
    발생한 문제: user_account_tb의 user_id에 값이 채워지지 않음

    원인 분석

    1. 트랜잭션 커밋 타이밍
        • User 엔티티 저장 후 즉시 ID가 할당되지 않을 수 있음
        • UserAccount 엔티티에서 User의 ID를 참조할 수 없는 상태
    1. 영속성 컨텍스트 플러시 미발생
        • JPA는 트랜잭션 커밋 시점에 실제 INSERT 수행
        • 중간에 ID가 필요한 경우 명시적 처리 필요
    notion image

    해결 방법

    @Transactional로 두 Insert를 하나의 트랜잭션으로 묶기
    @Service @RequiredArgsConstructor public class UserService { private final UserRepository userRepository; private final PasswordEncoder passwordEncoder; @Transactional public void 회원가입(UserRequest.JoinDTO joinDTO) { // 1. User 엔티티 저장 User user = joinDTO.toEntity(passwordEncoder); userRepository.join(user); // 2. User 엔티티가 영속화되고 ID 생성됨// 3. 생성된 User를 참조하여 UserAccount 저장 UserAccount userAccount = joinDTO.toEntity(user); userRepository.join2(userAccount); } }
     
    Repository 구현
    @Repository @RequiredArgsConstructor public class UserRepository { private final EntityManager em; public void join(User user) { em.persist(user); // persist 후 User에 ID가 자동 할당됨 } public void join2(UserAccount userAccount) { em.persist(userAccount); } }

    작동 원리

    1. @Transactional 시작 ↓ 2. User 엔티티 persist → JPA가 User에 ID 자동 할당 (영속성 컨텍스트) ↓ 3. UserAccount 엔티티 생성 (User의 ID 참조 가능) ↓ 4. UserAccount 엔티티 persist ↓ 5. @Transactional 종료 → 실제 DB에 커밋
    💡
    - `@Transactional`로 두 작업을 하나의 트랜잭션으로 묶음 - `em.persist()` 호출 시 ID가 영속성 컨텍스트에서 즉시 생성됨 - 순서가 중요: User 저장 → UserAccount 저장
    Share article

    silver

    RSS·Powered by Inblog