JPA 순환 참조 끊기

£€€.T.$·2023년 7월 4일
0

User.class

@Id // 해당 필드가 primary key임을 지정
@Column(name = "user_id")
@GeneratedValue(strategy = GenerationType.AUTO)
@OnDelete(action = OnDeleteAction.CASCADE)
private long userId;
    
@OneToMany(mappedBy = "user", cascade = CascadeType.ALL)
private List<Qna> qnas = new ArrayList<>();

Qna.class

@OneToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "user_id")
private User user;

qna 엔티티 자체를 검색시 순환 참조에 빠질 수 있다.

qna -> user_id -> qnas -> user_id... 반복 이 같은 경우

  1. @JsonIgnore
  2. @JsonManagedReference @JsonBackReference
  3. ⭐DTO 참조 (추천)

크게 위와 같은 방법이 있다.


1. @JsonIgnore

Qna.class

@OneToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "user_id")
@JsonIgnore
private User user;

qna(자식)엔티티에 어노테이션을 걸어준다.


2. @JsonManagedReference @JsonBackReference

User.class

@Id // 해당 필드가 primary key임을 지정
@Column(name = "user_id")
@GeneratedValue(strategy = GenerationType.AUTO)
@OnDelete(action = OnDeleteAction.CASCADE)
private long userId;
    
@OneToMany(mappedBy = "user", cascade = CascadeType.ALL)
@JsonManagedReference 
private List<Qna> qnas = new ArrayList<>();

Qna.class

@OneToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "user_id")
@JsonBackReference
private User user;

부모에 @JsonManagedReference
자식에 @JsonBackReference 를 걸어준다


3. DTO를 참조

AdminPageHeadController.class
@PostMapping("/qnaLoadList")
public ResponseEntity<List<QnaDto>> newQnaList(@RequestBody Map<String, String> qnaData){
   String qnaStatus = qnaData.get("qnaStatus");
   System.out.println(qnaStatus);
   List<QnaDto> list = qnaService.getStatusQnaList(qnaStatus);
   return new ResponseEntity<>(list, HttpStatus.OK);
}

User.class

@Id // 해당 필드가 primary key임을 지정
@Column(name = "user_id")
@GeneratedValue(strategy = GenerationType.AUTO)
@OnDelete(action = OnDeleteAction.CASCADE)
private long userId;
    
@OneToMany(mappedBy = "user", cascade = CascadeType.ALL)
private List<Qna> qnas = new ArrayList<>();

Qna.class

@OneToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "user_id")
private User user;

QnaService.class

public List<QnaDto> getStatusQnaList(String qnaStatus){
    System.out.println(qnaStatus);
    List<Qna> qnaList = qnaRepository.findByQnaStatus(QnaStatus.valueOf(qnaStatus));
    List<QnaDto> qnaDtos = new ArrayList<>();
        for(Qna qna : qnaList){
            QnaDto qnaDto = new QnaDto();
            qnaDto.setUserId(qna.getUser().getUserId());
            qnaDtos.add(qnaDto);
        }
        return qnaDtos;
    }

DTO 에서 set아무 값이나 반환하여 준다.


userservice.class

public boolean getUserList(String userEmail, String userPassword){
    List<User> userList = userRepository.findByUserEmailAndUserPwd(userEmail,userPassword);
    List<UserDto> userDtos = new ArrayList<>();
    for(User user : userList){
       UserDto userDto = new UserDto();
       userDto.setUserEmail(user.getUserEmail());
       userDto.setUserPwd(user.getUserPwd());
       userDtos.add(userDto);
    }
    if(userDtos.isEmpty())return false;
    else return true;
    }

로그인 시 userEmail과 userPassword를 받아와 해당 쿼리문으로 결과를 userList에 받아온다.

이 userList를 UserDto에 넣어 새로운 배열로 만들어 준다.

이 때 userEmail과 userPassword가 맞지 않아 결과가 없다면 userDtos는 빈 배열이 될 것 이다.

userDtos.isEmpty()로 빈배열을 확인하여 조건이 맞다면 false로 로그인이 실패하게되고 배열이 있다면 true로 로그인이 성공하게된다.

profile
Be {Nice} Be {Kind}

0개의 댓글