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

silver's avatar
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