트러블슈팅

[Spring Data JPA] 무한참조 문제 - @JsonIgnoreProperties

pyogowoon 2023. 1. 10. 15:22

 

 

@PutMapping("/api/user/{id}")
public CMRespDto<?> update(
        @PathVariable int id,
        @Valid UserUpdateDto userUpdateDto,
        BindingResult bindingResult, // 꼭@Valid가 적힌 다음파라메터에 적어야함
        @AuthenticationPrincipal PrincipalDetails principalDetails) {


    if (bindingResult.hasErrors()) {
        Map<String, String> errorMap = new HashMap<>();

        for (FieldError error : bindingResult.getFieldErrors()) {
            errorMap.put(error.getField(), error.getDefaultMessage());
        }
        throw new CustomValidationApiException("유효성검사 실패", errorMap);
    } else {

        User userEntity = userService.회원수정(id, userUpdateDto.toEntity());
        principalDetails.setUser(userEntity);
        return new CMRespDto<>(1, "회원수정완료", userEntity);
        //응답시에 userEntity의 모든 getter 함수가 호출되고 JSON으로 파싱하여 응답한다.
        //이것 역시 또 List<Image>의 무한반복 문제.


    }

}

 맨 마지막줄 return new CMRespDto<>(1,"회원수정완료",userEntity); 에서

로직이 실행될 때 userEntity의 모든 getter 함수가 호출되고 JSON으로 파싱하여 응답되는데

 이것 역시 List<image> 를 통해 User로 들어가는 무한반복 문제에 빠진다.

 

이런경우 image를 타고 들어가서 User를 읽을 때를 막아주면 해결되는데 이는

 

 

@Builder
@AllArgsConstructor
@NoArgsConstructor
@Data
@Entity
public class User {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private int id;

    @Column(unique = true, length = 20)
    private String username;

    @Column(nullable = false)
    private String password;

    private String name;
    private String website;  //웹사이트
    private String bio; // 자기소개

    @Column(nullable = false)
    private String email;
    private String phone;
    private String gender;

    private String profileImageUrl;
    private String role;

    private LocalDateTime createDate;


    @JsonIgnoreProperties("user")
    @OneToMany(mappedBy ="user", fetch= FetchType.LAZY)  //user는 Image의 변수를 넣어야함 //나는 연관관계의 주인이 아니다 를 알리는것.
    //이걸 함으로써 DB가 컬럼을 만들지않으며 select 할때 user Id로 등록된 image들을 다 가져옴
    // Lazy = User를 select할떄 해당 User id로 등록된 image들을 가져오지마 - 대신 getImages() 메소드가 호출될 때 가져와
    // Eaguer = User를 select할때 해당 user Id로 등록된 image들을 전부 join해서 가져와!
    private List<Image> images; // 양방향 매핑    /   DB는 여러개못들어감 (리스트가 뭔지모름)

    @PrePersist  // DB에 INSERT 되기 직전에 실행
    public void createDate(){
        this.createDate = LocalDateTime.now();
    }

}

 User 도메인의 List<Image> images; 필드에

 @JsonIgnoreProperties("변수이름") 을 지정해주면 해당 필드를 JSON파싱하지 않는다

즉 Images의 안에 user를 읽지않는다는 뜻