강의를 들으며 생각 정리 + "자바 ORM 표준 JPA 프로그래밍" 책 참고
예제 도메인 모델과 동작확인
앞으로 스프링 데이터 JPA 학습시 사용할 예제 도메인 모델을 설계하자.
도메인 모델은 단순하게 회원(Member) - 팀(Team) 엔티티가 다대일 양방향 연관관계를 맺도록 설계한다.
</entity/Member>
@Entity
@Getter
@Setter
@NoArgsConstructor(access = AccessLevel.PROTECTED)
@ToString(of = {"id", "username", "age"})
public class Member {
@Id
@GeneratedValue
@Column(name = "member_id")
private Long id;
private String username;
private int age;
@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "team_id")
private Team team;
public Member(String username) {
this.username = username;
}
public Member(String username, int age, Team team) {
this.username = username;
this.age = age;
if (team != null) {
changeTeam(team);
}
}
public void changeTeam(Team team) {
this.team = team;
team.getMembers().add(this);
}
}
</entity/Team>
@Entity
@Getter
@Setter
@NoArgsConstructor(access = AccessLevel.PROTECTED)
@ToString(of = {"id", "name"})
public class Team {
@Id
@GeneratedValue
@Column(name = "team_id")
private Long id;
private String name;
@OneToMany(mappedBy = "team")
private List<Member> members = new ArrayList<>();
public Team(String name) {
this.name = name;
}
}
@NoArgsConstructor AccessLevel.PROTECTED : JPA 스펙상 기본 생성자를 열어두어야 한다. 외부에서 기본 생성자로 접근하는 것을 막기 위해 protected로 열어둔다.
@ToString : 가급적 내부 필드만 출력 (연관관계인 엔티티를 ToString에 포함하면 무한루프의 위험성이 있다)
Member -> changeTeam() : 양방향 연관관계 한번에 처리 (연관관계 편의 메서드)
+) Member가 Team을 바꾸면 기존 team.getMembers()에서는 Member를 삭제해야 하지 않나?
: Team은 연관관계의 주인이 아니므로 JPA 동작에 영향을 주지 않기 때문에 따로 삭제할 필요 없다. Member가 연관관계의 주인이고 DB에서 연관관계를 나타낼 때, Member 테이블의 외래키에만 의존한다.
확실하게 컬렉션에서 삭제를 해도 되지만 너무 복잡해지고, JPA와 DB 변경에 영향을 주지 않아서 이런 부분은 생략해도 된다.
간단하게 테스트 해본다.
@SpringBootTest
@Transactional
@Rollback(false)
class MemberTest {
@PersistenceContext
EntityManager em;
@Test
public void testEntity() {
//given
Team teamA = new Team("teamA");
Team teamB = new Team("teamB");
em.persist(teamA);
em.persist(teamB);
Member member1 = new Member("member1",10,teamA);
Member member2 = new Member("member2",20,teamA);
Member member3 = new Member("member3",30,teamB);
Member member4 = new Member("member4",40,teamB);
em.persist(member1);
em.persist(member2);
em.persist(member3);
em.persist(member4);
//초기화
em.flush();
em.clear();
//when
List<Member> members = em.createQuery("select m from Member m", Member.class)
.getResultList();
//then
for (Member member : members) {
System.out.println("member = " + member);
System.out.println("-> member.team = " + member.getTeam());
}
}
}
-> DB 테이블 결과 확인, 지연 로딩 동작 확인
'java > jpa' 카테고리의 다른 글
[Spring Data JPA] 쿼리 메소드 기능 (0) | 2021.05.24 |
---|---|
[Spring Data JPA] 공통 인터페이스 기능 (0) | 2021.05.23 |
[Spring Data JPA] 프로젝트 환경설정 (0) | 2021.05.23 |
[JPA] 쿼리 파라미터 로그 남기기 (0) | 2021.05.23 |
[JPA] API 개발 고급 - 실무 필수 최적화 (1) | 2021.05.21 |