[SPRING] JPA 순환 참조

JPA에서 양방향 매핑 설정 후 유저 정보 조회를 하는 과정에서 무한히 서로를 참조하는 에러가 발생하였다.

/service/UserService.java

Spring Data JPA를 이용하여 유저정보를 조회하는 코드 작성하였다.

public User findUser(String username) {
    return userRepository.findByUsername(username);
}

에러 발생

구글링을 해보니 @JsonIgnore 어노테이션을 사용할 수 도 있지만 DTO를 만드는 것이 효과적이라고 한다.

User의 모든 정보를 보기 위해 UserDto는 User의 모든 필드를 포함하도록 작성하였다.

** domain/dto/UserDto.java
** domain/dto/MemoDto.java
** domain/dto/CategoriyDto.java

// ** domain/dto/UserDto.java


@Data
@NoArgsConstructor
@AllArgsConstructor
public class UserDto {

      private Long id;
      private String username;
      private String password;
      private String email;
      private LocalDateTime createDateTime;
      private List<MemoDto> memoDtos = null;
      private List<CategoryDto> categoryDtos = null;
 
 }

// ** domain/dto/MemoDto.java

@Data
@NoArgsConstructor
@AllArgsConstructor
public class MemoDto {

      private StackType stackType;
      private String question;
      private String answer;

      public MemoDto(Memo memo) {
            this.stackType = memo.getStackType();
            this.question = memo.getQuestion();
            this.answer = memo.getAnswer();
      }
}

// ** domain/dto/CategoriyDto.java
@Data
@AllArgsConstructor
@NoArgsConstructor
public class CategoryDto {
      private StackType stackType;

      public CategoryDto(Category category) {
            this.stackType = category.getStackType();
      }
}

를 작성후에 User 객체에서 UserDto 객체로 변환시키는 메서드를 만들었다.

** domain/dto/UserDto.java
** service/UserService.java

// ** domain/dto/UserDto.java

public UserDto user2Dto(User user) {
    UserDto userDto = new UserDto();
    userDto.setId(user.getId());
    userDto.setEmail(user.getEmail());
    userDto.setPassword(user.getPassword());
    userDto.setUsername(user.getUsername());
    userDto.setCreateDateTime(user.getCreateDateTime());


    List<CategoryDto> categoryDtos = new ArrayList<>();
    for(Category category : user.getCategoryList()) {
          categoryDtos.add(new CategoryDto(category));
    }
    userDto.setCategoryDtos(categoryDtos);

    List<MemoDto> memoDtos = new ArrayList<>();
    for(Memo memo : user.getMemoList()) {
          memoDtos.add(new MemoDto(memo));
    }
    userDto.setMemoDtos(memoDtos);

    return userDto;
}

// ** service/UserService.java

public UserDto findUser(String username) {
    User user = userRepository.findByUsername(username);
    return new UserDto().user2Dto(user);
}

Postman 결과 화면

{
    "statusCode": 200,
    "data": {
        "id": 1,
        "username": "jung",
        "password": "1234",
        "email": "hoyoung2@hufs.ac.kr",
        "createDateTime": "2023-09-10T22:29:31.677712",
        "memoDtos": [],
        "categoryDtos": [
            {
                "stackType": "JAVA"
            },
            {
                "stackType": "PYTHON"
            }
        ]
    }
}

서로 무한히 순환참조하지 않고 리턴에 성공할 수 있었다.

'🍃 스프링' 카테고리의 다른 글

[SPRING] H2 DB 연결 중 에러 정리  (0) 2024.01.15
[SPRING] ResponseDTO  (0) 2023.08.28
[SPRING] GET API Query String  (0) 2023.08.26
[SPRING] 컬렉션  (0) 2023.07.30
[SPRING] Entity, DTO  (0) 2023.07.24