Entity의 연관 관계 - @ManyToOne -
N 대 1 관계
@ManyToOne
N 대 1 관계를 맺어주는 역할을 한다.
고객 Entitiy와 상품 Entity가 N : 1 관계라고 가정
단방향 관계
Product Entity가 N의 관계로 외래 키의 주인
Product Entity
import jakarta.persistence.*;
import lombok.Getter;
import lombok.NoArgsConstructor;
@Entity
@Getter
@NoArgsConstructor
public class Product {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
private String name;
private double price;
@ManyToOne
@JoinColumn(name = "user_id")
private User user;
public Product(String name, double price) {
this.name = name;
this.price = price;
}
}
@JoinColumn은 생략해도
"user"에 자동적으로 "_id"를 추가해 주므로 큰 영향은 없다.
하지만 다른 사람이 봤을 때를 생각하여
명시적으로 지정해 주는 것이 협업을 할 때 좋다.
User Entity
import jakarta.persistence.*;
import lombok.Getter;
import lombok.NoArgsConstructor;
@Entity
@Getter
@Table(name = "users")
@NoArgsConstructor
public class User {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
private String name;
public User(String name) {
this.name = name;
}
}
테스트 코드
package com.practice.practice.relation;
import com.practice.practice.entity.Product;
import com.practice.practice.entity.User;
import com.practice.practice.repository.ProductRepository;
import com.practice.practice.repository.UserRepository;
import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.annotation.Rollback;
import org.springframework.transaction.annotation.Transactional;
@SpringBootTest
@Transactional
public class ManyToOneTest {
@Autowired
ProductRepository productRepository;
@Autowired
UserRepository userRepository;
@Test
@Rollback(value = false)
@DisplayName("N대1 단방향 테스트")
void test1() {
Product product = new Product("곰인형", 15000);
productRepository.save(product);
Product product2 = new Product("미미인형", 17000);
productRepository.save(product2);
User user = new User("John");
userRepository.save(user);
product.setUser(user);
product2.setUser(user);
}
}
결과
Hibernate:
create table product (
id bigint not null auto_increment,
name varchar(255),
price float(53) not null,
user_id bigint,
primary key (id)
) engine=InnoDB
Hibernate:
create table users (
id bigint not null auto_increment,
name varchar(255),
primary key (id)
) engine=InnoDB
Hibernate:
alter table product
add constraint FK47nyv78b35eaufr6aa96vep6n
foreign key (user_id)
references users (id)
Hibernate:
/* insert com.practice.practice.entity.Product
*/ insert
into
product (name, price, user_id)
values
(?, ?, ?)
Hibernate:
/* insert com.practice.practice.entity.Product
*/ insert
into
product (name, price, user_id)
values
(?, ?, ?)
Hibernate:
/* insert com.practice.practice.entity.User
*/ insert
into
users (name)
values
(?)
Hibernate:
/* update
com.practice.practice.entity.Product */ update product
set
name=?,
price=?,
user_id=?
where
id=?
Hibernate:
/* update
com.practice.practice.entity.Product */ update product
set
name=?,
price=?,
user_id=?
where
id=?
두개의 상품 정보를 넣어주어
update product가 두 번 되었다.
"곰인형"과 "미미인형"의 "user_id"가 같다.
양방향 관계
양방향 참조를 위해 고객 Entity에서 Java 컬렉션을 사용하여 상품 Entity를 참조한다.
Product Entity
import jakarta.persistence.*;
import lombok.Getter;
import lombok.NoArgsConstructor;
@Entity
@Getter
@NoArgsConstructor
public class Product {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
private String name;
private double price;
@ManyToOne
@JoinColumn(name = "user_id")
private User user;
public Product(String name, double price) {
this.name = name;
this.price = price;
}
}
User Entity
import jakarta.persistence.*;
import lombok.Getter;
import lombok.NoArgsConstructor;
import java.util.ArrayList;
import java.util.List;
@Entity
@Getter
@Table(name = "users")
@NoArgsConstructor
public class User {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
private String name;
@OneToMany(mappedBy = "user")
private List<Product> productList = new ArrayList<>();
public User(String name) {
this.name = name;
}
}
양방향에서
N : 1의 반대의 입장에서는
1 : N이 되므로
고객 Entity는 @OneToMany의 관계이다.
양방향 연관관계를 위해 mappedBy를 사용한다.
테스트 코드
@Test
@Rollback(value = false)
@DisplayName("N대1 양방향 테스트")
void test2() {
Product product = new Product("곰인형", 15000);
productRepository.save(product);
Product product2 = new Product("미미인형", 17000);
productRepository.save(product2);
User user = new User("John");
userRepository.save(user);
// User Entity 를 통해 Food Entity 를 참조해보겠습니다.
user.addProductList(product);
user.addProductList(product2);
}
User Entity에 추가
public void addProductList(Product product) {
this.productList.add(product);
}
결과
Hibernate:
create table product (
id bigint not null auto_increment,
name varchar(255),
price float(53) not null,
user_id bigint,
primary key (id)
) engine=InnoDB
Hibernate:
create table users (
id bigint not null auto_increment,
name varchar(255),
primary key (id)
) engine=InnoDB
Hibernate:
alter table product
add constraint FK47nyv78b35eaufr6aa96vep6n
foreign key (user_id)
references users (id)
Hibernate:
/* insert com.practice.practice.entity.Product
*/ insert
into
product (name, price, user_id)
values
(?, ?, ?)
Hibernate:
/* insert com.practice.practice.entity.Product
*/ insert
into
product (name, price, user_id)
values
(?, ?, ?)
Hibernate:
/* insert com.practice.practice.entity.User
*/ insert
into
users (name)
values
(?)
insert 3개는 잘 날아왔다.
"product table"의 "user_id"가 null로 들어가 있다.
addProductList 수정하고 다시 테스트
public void addProductList(Product product) {
this.productList.add(product);
product.setUser(this);
}
결과
Hibernate:
/* insert com.practice.practice.entity.Product
*/ insert
into
product (name, price, user_id)
values
(?, ?, ?)
Hibernate:
/* insert com.practice.practice.entity.Product
*/ insert
into
product (name, price, user_id)
values
(?, ?, ?)
Hibernate:
/* insert com.practice.practice.entity.User
*/ insert
into
users (name)
values
(?)
Hibernate:
/* update
com.practice.practice.entity.Product */ update product
set
name=?,
price=?,
user_id=?
where
id=?
Hibernate:
/* update
com.practice.practice.entity.Product */ update product
set
name=?,
price=?,
user_id=?
where
id=?
update 2번이 추가되었다.
더 이상 null로 들어오지 않는다.
3번째와 4번째 상품을 주문한 "user_id"가 같음을 알 수 있다.
먼저 "user_id"가 auto_increment에 의해 2가 되었다.
그 후 저장이 되고
"user_id"가 2인 것을 파악한 후 상품 주문이 등록되었다.
내용 참고 - 스파르타 코딩클럽 -
'자바 탐구' 카테고리의 다른 글
JPA) Entity의 연관 관계 - @ManyToMany - (0) | 2023.05.03 |
---|---|
JPA) Entity의 연관 관계 - @OneToMany - (0) | 2023.05.03 |
JPA) Entity의 연관 관계 - @OneToOne - (0) | 2023.05.02 |
JPA) 데이터베이스 테이블과 Entity의 연관 관계 표현 차이 (0) | 2023.05.02 |
인텔리제이) MySQL 연동하기 (0) | 2023.04.30 |