사전정의
@SpringBootTest
@Transactional
public class TestClass {
@Autowired
EntityManager em;
@BeforeEach
void setUp() {
Team team = new Team("team1", "팀1");
em.persist(team);
Member member1 = new Member("member1", "회원1");
member1.setTeam(team);
em.persist(member1);
em.flush();
}
@AfterEach
void tearDown() {
em.flush();
em.close();
}
저장
package com.example.springboot3.test;
import com.example.springboot3.entity.Member;
import com.example.springboot3.entity.Team;
import jakarta.persistence.EntityManager;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.transaction.annotation.Transactional;
@SpringBootTest
public class TestClass {
@Autowired
EntityManager em;
@Test
@Transactional(readOnly = false)
public void testSave() {
// 팀1 저장
Team team1 = new Team("team1", "팀1");
em.persist(team1); // 영속화
// 회원1 저장
Member member1 = new Member("member1", "회원1");
member1.setTeam(team1); // 연관관계 설정 member1 -> team1
em.persist(member1); // 영속화
// 회원2 저장
Member member2 = new Member("member2", "회원2");
member2.setTeam(team1); // 연관관계 설정 member2 -> team1
em.persist(member2); // 영속화
em.flush(); // 영속성 컨텍스트에 있는 내용을 DB에 반영
}
}
insert into team (name, team_id) values ('팀1', 'team1');
insert into member (team_id, username, member_id) values ('team1', '회원1', 'member1');
insert into member (team_id, username, member_id) values ('team1', '회원2', 'member2');
- flush 되면서 db에 한번에 쿼리가 날아간다.
조회
객체 그래프 탐색 조회
@Test
void find() {
Member member = em.find(Member.class, "member1");
Team team = member.getTeam();// 객체그래프의 탐색
System.out.println("team = " + team.getName());
}
team = 팀1
- 객체의 연관관계를 사용하여 조회하는 방법
객체지향쿼리 사용(JPQL)
- JPQL 을 사용하여 연관관계를 갖는 엔티티를 조회
@Test
void find_JPQL() {
String jpql = "select m from Member m join m.team t where t.name=:teamName";
List<Member> resultList = em
.createQuery(jpql, Member.class)
.setParameter("teamName", "팀1")
.getResultList();
for (Member member : resultList) {
System.out.println("[query] member.username=" + member.getUsername());
}
select m1_0.member_id,m1_0.team_id,m1_0.username from member m1_0 join team t1_0 on t1_0.team_id=m1_0.team_id where t1_0.name='팀1';
[query] member.username=회원1
수정
void update() {
// 새로운 팀2
Team team2 = new Team("team2", "팀2");
em.persist(team2);
// 회원1에 새로운 팀2 설정
Member member = em.find(Member.class, "member1");
member.setTeam(team2);
em.flush();
}
insert into team (name, team_id) values ('팀1', 'team1');
update member set team_id='team2', username='회원1' where member_id='member1';
- em.update() 같은 메서드가 없다.
- 단순히 엔티티의 값만 변경해두면 트랜잭션을 커밋시에 플러시가 일어난다.
- 테스트 코드의 경우 별도 트랜잭션 커밋이 발생하지 않음.
- 그래서 em.flush() 를 호출해줘야 변경감지 기능이 동작함.
- 변경감지 이후에 DB에 자동적으로 반영함.
- 연관관계 수정시도 동일함.
- 참조하는 대상만 변경한다면 나머지는 JPA 가 자동으로 처리
연관관계의 제거
- 특정 엔티티의 연관관계를 어떻게 제거하는지에 다룬다.
Member
엔티티의setTeam()
메서들을 사용하여 연관된Team
엔티티와의 연관을 제거가능
@Test
void relation_remove() {
Member member1 = em.find(Member.class, "member1");
member1.setTeam(null);
}
update member set team_id=NULL, username='회원1' where member_id='member1';
- 위의 쿼리가 나가게 됩니다.
연관된 엔티티의 삭제
- 연관된 엔티티를 삭제 전,
- 해당 엔티티와 연결된 모든 연관관계를 제거해야함
@Test
void relation_entity_remove() {
Team team = em.find(Team.class, "team1");
Member member1 = em.find(Member.class, "member1");
member1.setTeam(null);
em.remove(team);
}
update member set team_id=NULL, username='회원1' where member_id='member1';
delete from team where team_id='team1';
만약 연관된 엔티티를 삭제전에 연관관계를 제거하지 않았다면, 어떤 문제가 발생할까?
- 외래 키 제약조건 때문에 데이터베이스에서 오류가 발생함.
- 해당 엔티티를 참조하는 다른 엔티티가 아직 존재하기 때문에 발생
Uploaded by N2T
'자바 > JPA' 카테고리의 다른 글
[5단원] 단방향 연관관계 (0) | 2023.11.01 |
---|---|
[5단원] `@JoinColumn` , `@ManyToOne` (0) | 2023.11.01 |
[5단원] 양방향 연관관계의 매핑 (0) | 2023.11.01 |
[5단원] 양방향 매핑의 규칙 : 연관관계의 주인 (0) | 2023.11.01 |
[6단원] 다대일 단방향 [N:1] 연관관계 (0) | 2023.11.01 |