[Trouble Shooting] JPA에서 부모 엔티티에 값이 미등록될 때의 원인과 해결 전략

k·2024년 2월 8일
0

Trouble Shooting

목록 보기
2/3

사건 개요

관계에 대한 코드를 짜고, 테스트 케이스를 돌리던 중에 발생했다.

User Entity와 Post Entity를 만들었고, @OneToMany@ManyToOne그리고 @JoinColumn에 대한 셋팅을 모두 마친 상태였다.

@SpringBootTest
public class UserRepositoryTests {

	@Autowired
	private UserRepository userRepository;

	@Autowired
	private PostRepository postRepository;

	@Test
	@Transactional
	public void testUserAndPostCreation() {
		// Create a user
		User user = new User("john.doe", "password123", "John Doe");
		userRepository.save(user);

		// Create a post
		Post post = new Post("Test Post", "This is a test post.", user);
		postRepository.save(post);

		// Retrieve user and post from the database
		Optional<User> savedUserOptional = userRepository.findByUserId("john.doe");
		assertThat(savedUserOptional).isNotEmpty();
		User savedUser = savedUserOptional.get();

		Post savedPost = postRepository.findById(post.getId()).orElse(null);

		// Assertions using AssertJ
		assertThat(savedUser.getUserId()).isEqualTo(user.getUserId());
		assertThat(savedUser.getPosts().size()).isEqualTo(1); // Check if the user has one post

		assertThat(savedPost).isNotNull();
		assertThat(savedPost.getTitle()).isEqualTo(post.getTitle());
		assertThat(savedPost.getContent()).isEqualTo(post.getContent());
		assertThat(savedPost.getAuthor()).isEqualTo(user);

		// Additional assertion for the relationship
		List<Post> userPosts = savedUser.getPosts();
		assertThat(userPosts.size()).isEqualTo(1);
		assertThat(userPosts.get(0)).isEqualTo(savedPost);
	}
}

위는 테스트 케이스이다.

내가 이해하는 것으로는 Post를 작성하면, 해당되는 User 객체 내에서도 추가된 Post 가 있어야하는데 실제로는 존재하지않았다.

마지막 3줄쪽 테스트케이스에서 문제가 발생한 것이다.

List<Post> userPosts = savedUser.getPosts();
		assertThat(userPosts.size()).isEqualTo(1);
		assertThat(userPosts.get(0)).isEqualTo(savedPost);

엔티티에 대한 관계가 잘못된 줄 알고, 스택오버플로우에도 물어봤지만 내가 설정한 관계에서 잘못된 부분이 없었다.

그러다가 문득 Post를 만들 때, 생성자에서 참조된 User 객체내에 Post를 추가하지않아서 안된게 아닐까 라는 생각이 들었다.

그렇게 내가 생각한 방법대로 코드를 수정했고, 다시 테스트를 해본 결과 성공적으로 테스트 케이스에 통과 했다.

해결방법

기존코드

public Post(String title, String content, User author) {
        this.title = title;
        this.content = content;
        this.author = author;
}

위는 문제의 생성자 코드이다. Post에서는 User를 넣어줬는데 User에서 Post를 담아주지 않았다고 생각되어서 아래와 같이 수정했다.

변경된 코드

public Post(String title, String content, User author) {
        this.title = title;
        this.content = content;
        this.author = author;
        author.getPosts().add(this);
}

author.getPosts().add(this); 이 부분만 추가해줬을 뿐인데 테스트케이스가 성공적으로 수행되었다.

JPA가 자동으로 해주는게 많다보니, 이러한 부분도 자동으로 해줄 것이라고 생각 했던 것이다.

아마 이런 문제로 고생하는 사람이 꽤나 있을 것 같아서 따로 정리해서 올리게 되었다.

마무리

JPA 의 관계에서 대한 공부를 시작한지 얼마 안돼서 미흡했었던 것 같다.

스프링부트내에서 자동으로 해주는 부분이 많다고 해서 모든 기능이 자동으로 되어있지는 않다. 항상 문제가 발생하면 의심하는 습관을 가져보자.

profile
You must do the things you think you cannot do

0개의 댓글