양방향 연관관계에서 중요한 것
알고 가야할 것
1. DB는 FK(외래키)하나로 관계를 맺은 Table을 탐색할 수 있다
2. DB랑은 다르게 객체는 객체안에 탐색하고 싶은 객체와 참조를 맺어놔야 탐색이 가능하다
3. 양방향 매핑은 단방향 매핑과 다르게 주인을 정해줘야 한다 (주인이 아니라면 조회밖에 하지 못한다)
코드를 보면
Member
@Entity
@Table(name = "member")
@Getter
@Setter
@Data
@NoArgsConstructor
@AllArgsConstructor
public class Member {
@Id
@Column(name = "member_id")
private Long member_id;
@Column(name = "id")
private String id;
@Column(name = "pw")
private String pw;
@OneToMany(mappedBy= "member")
private List<Post> posts = new ArrayList<Post>();
public void addPost(Post post) {
this.posts.add(post);
}
}
위처럼 Member가 @OneToMany로 1:N관계에서 1이라고 볼 수 있습니다
여기서 mappedBy는 내가 주인이 아니다라고 생각하고 넘어가시면 되겠습니다
Post
@Entity
@Table(name = "post")
@Getter
@Setter
@Data
@NoArgsConstructor
@AllArgsConstructor
public class Post {
@Id
@Column(name = "post_id")
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long post_id;
@Column(name = "title")
private String title;
@Column(name = "content")
private String content;
@Column(name = "picture")
private String post_picture;
@Column(name = "likes")
private String likes;
@Column(name = "comment")
private String comment;
@ManyToOne
@JoinColumn(name="member_id") //중복 안되게 Post테이블의 id필드랑
private Member member;
}
@ManyToOne은 1:N에서 N을 맞게다는 뜻입니다
@JoinColumn은 member객체의 member_id를 Join 쉽게 말해 Fk로 쓰겠다 입니다
Post(연관관계의 주인)에 값을 넣으면 member_id랑 Join해서 Post Table에는 member_id를 외래키로 가지게 됩니다
MemberController
@RequestMapping("/api")
@RestController
public class MemberController {
@Autowired
MemberService memberService;
@PostMapping("/member/join")
public String join(@RequestParam("member_id") Long member_id,
@RequestParam("id") String id,
@RequestParam("pw") String pw) {
return memberService.join(member_id, id,pw);
}
}
여기서 먼저 회원가입으로 member_id, id, pw값을 Param으로 받습니다
MemberService
@Service
@Transactional
public class MemberService {
@Autowired
MemberRepository memberRepository;
PostRepository postRepository;
public String join(Long member_id, String id, String pw) {
try {
Member member = new Member();
member.setMember_id(member_id);
member.setId(id);
member.setPw(pw);
System.out.println("start post");
Post post = new Post();
post.setComment("Comment");
post.setPost_picture("PI");
post.setContent("content");
post.setTitle("title");
post.setLikes("LIkes");
post.setMember(member);
//member.addPost(post);
memberRepository.save(member);
postRepository.save(post);
}catch(Exception e){
return e.getMessage();
}
return "성공!"
}
이상하죠 member에 값을 넣어봤자 DB에 반영이 안된다고 했는데 왜 저장을 하는 걸 까?
주석으로 처리 된 코드를 보면 사실상 우리가 post에서 DB에 값만 넣을 거고 member를 조회하지 않을 거다라고 하면 상관은 없습니다 하지만 양방향 매핑에서 우리는 member도 조회할 것이기 대문에 양쪽모두 값을 넣어 어떠한 경우에도 조회가 가능하도록 만들어야 합니다
cascade = CascadeType.ALL
다른 경우로 위처럼 cascade를 사용해서 하는 방법(member를 저장하지 않고하는)이 있지만 이번 경우에는 알아가는 목적으로 코드를 작성해 그러지 않았습니다
그리고 JPA의 Save()메소드는 @Entity가 붙은 class에서 @Id가 붙어있는지 확인하고 Select후 Insert합니다 DB에 데이터가 존재한다고 생각해서 말이죠
만약 Id값을 이미 알고 있다면 쿼리를 줄일 수 있습니다 궁금하신분들은 밑에 사이트 참고하시면 될 거 같습니다
이해가 안 가신다면 밑에 김영한님 강의를 보시면 쉽게 이해할 수 있습니다!
https://www.youtube.com/watch?v=WfrSN9Z7MiA
질문 & 틀린점은 댓글 부탁드립니다
'스프링 > JPA' 카테고리의 다른 글
[JPA] EAGER Loading Vs LAZy Loading N+1이란? (0) | 2024.08.27 |
---|---|
[Spring] JPA에서 Entity Life의 Cycle은 어떻게 이루어지나?(면접 질문 있음) (0) | 2024.06.14 |
[Spring] JPA란 무엇인가 (1) | 2023.01.18 |