Room room = Room.builder()
.id(1L)
.game(game)
.tags(tags)
.build();
room.join(user);
roomRepository.save(room);
위와 같은 코드가 있는데 roomRepository.getById(1L)
해도 user가 비어있다. @Transactional
어노테이션을 붙이니 해결이 됐는데 원인을 모르겠다.
현재 추정: 트랜잭션과 변경 감지
roomRepository.save()
를 호출하면 트랜잭션을 기준으로 저장되는 것으로 추정된다. 따라서 위의 코드는@Transactional
이 없기 때문에 트랜잭션에 모아둔 커밋이 없기 때문에 단순하게 Room Entity 자체만 저장이 되는것같다. (users는 연관관계의 주인이 아니기때문에 저장되지 않는다.)JpaRepository
의 코드를 보기로 했다.JpaRepository
의 기본 구현체는SimpleJpaRepository
로 이 부분에save
메서드가 구현되어 있었다. 이 메서드에는@Transactional
이 붙어있다. 따라서, 기존 트랜잭션이 있으면 참여하고, 없으면 새로 생성한다. 영속선 컨텍스트는 일반적으로 트랜잭션은 커밋하면 플러쉬가 되고 엔티티가 준영속 상태가 된다. 따라서, 변경 감지는 트랜잭션 단위로 이루어지고 동기화가 되기때문에@Transactional
이 붙어있지 않은 경우는 변경 감지가 불가능해진다.
확인하기
만약 정말 트랜잭션과 변경 감지가 원인이라면,
@Transactional
이 없는 경우 실제 연관관계 주인인User
를 직접 수정해도Room
에 영향을 주지 못할 것이다. 트랜잭션 안이 아니라User
는 이미 준영속 상태기 때문이다. 아래 사진과 같이 여전히 실패하는 모습을 볼 수 있다.\

@Trnasactional
이 붙어있는 경우라면, 연관관계 주인이 아닌Room
이 호출되더라도 테스트가 통과된다.
참고 자료
https://happyer16.tistory.com/entry/Spring-jpa-save-saveAndFlush-제대로-알고-쓰기
https://www.popit.kr/jpa-변경-감지와-스프링-데이터/