목차
테이블 설계
다대일 연관관계를 고객이 주문한 음식(Food)과 고객(Member)을 예시로 설명하겠습니다.
- 여러가지의 음식(Food)은 한 명의 고객(Member)에게 주문될 수 있다.
- 음식(Food) : 고객(Member) = N : 1
단방향 연관관계를 위한 추가 조건은 다음과 같습니다.
- Food Entity는 Food.member 필드를 통해 음식을 주문한 고객(Member Entity)에 접근할 수 있다.
- Member Entity는 Food Entity에 접근할 수 없다.
Entity 관계 매핑
- Food Entity
- 다대일에서 다(Many)의 관계를 갖습니다.
@Entity
public class Food {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
private String name;
private double price;
@ManyToOne
@JoinColumn(name = "member_id")
private Member member;
// constructor, getter, setter, ...
}
- Member Entity
- 다대일에서 일(One)의 관계를 갖습니다.
@Entity
public class Member {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
private String name;
// constructor, getter, setter, ...
}
- 다대일 단방향 매핑에서는 다(Many)쪽에서 일(One)의 Entity를 참조 필드로 갖습니다.
- 참조 필드 위에
@ManyToOne
애노테이션과@JoinColumn(name = "{foreign key name}")
애노테이션을 추가로 작성합니다. - 위의 Entity 관계를 적용하여 테이블을 생성하였을 때, 실행되는 SQL은 아래와 같습니다.
create table food (
id bigint not null auto_increment,
name varchar(255),
price float(53) not null,
member_id bigint,
primary key (id)
);
create table member (
id bigint not null auto_increment,
name varchar(255),
primary key (id)
);
alter table food
add constraint FKnyfi1wxbgo0pqliou7xkfe4lw
foreign key (member_id)
references member (id)
Entity 관계 사용법
- 저장
@Transactional
@SpringBootTest
public class ManyToOneTest {
@Autowired FoodRepository foodRepository;
@Autowired MemberRepository memberRepository;
@Test
@Rollback(value = false)
@DisplayName("N대1 단방향 저장 테스트")
void OneWaySaveTest() {
// 고객(Member)1
Member member = new Member("Inyong");
memberRepository.save(member);
// 음식(Food)1
Food food1 = new Food("후라이드 치킨", 15000);
foodRepository.save(food1);
food1.setMember(member); // 외래 키 입력
// 음식(Food)2
Food food2 = new Food("양념 치킨", 20000);
foodRepository.save(food2);
food2.setMember(member); // 외래 키 입력
}
}
- 위 코드 실행 시, 적용되는 SQL은 다음과 같습니다.
- JPA의 변경감지와 Hibernate의 업데이트 기본 전략에 의해 UPDATE 문이 실행됩니다.
INSERT INTO MEMBER (NAME) VALUES ('Inyong');
INSERT INTO FOOD (MEMBER_ID, NAME, PRICE) VALUES (NULL, "후라이드 치킨", 15000);
INSERT INTO FOOD (MEMBER_ID, NAME, PRICE) VALUES (NULL, "양념 치킨", 20000);
UPDATE FOOD SET (MEMBER_ID=1, NAME="후라이드 치킨", PRICE=15000) WHERE FOOD_ID=1;
UPDATE FOOD SET (MEMBER_ID=1, NAME="양념 치킨", PRICE=20000) WHERE FOOD_ID=2;
- 조회
@Transactional
@SpringBootTest
public class ManyToOneTest {
@Autowired FoodRepository foodRepository;
@Autowired MemberRepository memberRepository;
@Test
@DisplayName("N대1 단방향 조회 : Food 기준 Member 정보 조회")
void OneWayViewTest() {
// 음식 정보 조회
Food food = foodRepository.findById(1L).orElseThrow(NullPointerException::new);
System.out.println("food.getName() = " + food.getName());
// 음식을 주문한 고객 정보 조회
System.out.println("food.getMember().getName() = " + food.getMember().getName());
}
}
// 출력 결과
// food.getName() = 후라이드 치킨
// food.getMember().getName() = Inyong
- 위 코드 실행 시, 적용되는 SQL은 다음과 같습니다.
SELECT f.ID, m.ID, m.NAME, f.NAME, f.PRICE FROM FOOD f
LEFT JOIN MEMBER m ON m.ID = f.MEMBER_ID
WHERE f.ID = 1
'JPA' 카테고리의 다른 글
[JPA] 다대일 연관관계 (양방향) (0) | 2023.04.29 |
---|---|
[JPA] 일대일 연관관계 (양방향) (0) | 2023.04.29 |
[JPA] 일대일 연관관계 (단방향) (0) | 2023.04.28 |
[JPA] Entity 연관 관계 (0) | 2023.04.28 |
[JPA] JPA 동작 이해하기 - 동작 원리와 영속성 컨텍스트 (0) | 2023.04.27 |
댓글