공급 업체 엔티티 클래스
@Entity
@Getter
@Setter
@NoArgsConstructor
@ToString(callSuper = true)
@EqualsAndHashCode(callSuper = true)
@Table(name = "provider")
public class Provider extends BaseEntity{
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
private String name;
}
Product entity에 공급업체 번호를 받기 위해 필드 추가
@OneToOne(mappedBy = "product")
@ToString.Exclude
ProductDetail productDetail;
@ManyToOne
@JoinColumn(name = "provider_id")
@ToString.Exclude
private Provider provider;
일반적으로 외래키를 가지고 있는 쪽에서 Owner 역할을 함
-> Product entity가 Provider의 주인
공급 업체 아이디가 추가 된것을 볼 수 있음
public interface ProviderRepository extends JpaRepository<Provider, Long> {
}
엔티티의 주인인 Product의 Repository를 활용해 테스트 진행
@Autowired
ProductRepository productRepository2;
@Autowired
ProviderRepository providerRepository;
@Test
void relationshipTest1(){
// 테스트 데이터 생성
Provider provider = new Provider();
provider.setName("삼성물산");
providerRepository.save(provider);
Product product = new Product();
product.setName("가위");
product.setPrice(5000);
product.setStock(500);
product.setProvider(provider);
productRepository2.save(product);
//테스트
System.out.println(
"product : " + productRepository2.findById(2L)
.orElseThrow(RuntimeException::new));
System.out.println("provider :" + productRepository2.findById(2L)
.orElseThrow(RuntimeException::new).getProvider());
}
product : Product(super=BaseEntity(createdAt=2022-11-02T19:29:06.223346, updatedAt=2022-11-02T19:29:06.223346), number=2, name=가위, price=5000, stock=500)
provider :Provider(super=BaseEntity(createdAt=2022-11-02T19:29:06.220650, updatedAt=2022-11-02T19:29:06.220650), id=1, name=삼성물산)
공급업체에서 등록된 상품을 조회하기 위한 일대다 연관관계 설정해보자
공급업체 entity 에 추가
@OneToMany(mappedBy = "provider", fetch = FetchType.EAGER)
@ToString.Exclude
private List<Product> productList = new ArrayList<>();
일대다 관게의 경우 여러 상품의 엔티티가 포함될 수 있어 컬렉션 형식으로 필드 작성
@OneToMany가 붙은쪽에서 @JoinColumn 사용 시 상대 엔티티에 외래키가 설정됨
@OneToMany의 기본 fetch 전략 Lazy 대신 즉시 로딩으로 수정하였음
이렇게 Provider 엔티티 클래스를 수정해도 애플리케이션을 가동하면 칼럼은 변경되지 않음
mappedBy
로 설정된 필드는 칼럼에 적용되지 않음!
-> 양쪽에서 연관관계 설정하고 있을 때 RDMS 형식으로 사용하기 위해 mappedBy를 통해 한쪽으로 외래키 관리를 위임한 것!
@Autowired
ProductRepository productRepository3;
@Autowired
ProviderRepository providerRepository3;
@Test
void relationshipTest(){
// 테스트 데이터 생성
Provider provider = new Provider();
provider.setName("삼성상사");
providerRepository3.save(provider);
Product product1 = new Product();
product1.setName("펜");
product1.setPrice(2000);
product1.setStock(100);
product1.setProvider(provider);
Product product2 = new Product();
product2.setName("가방");
product2.setPrice(2000);
product2.setStock(200);
product2.setProvider(provider);
Product product3 = new Product();
product3.setName("노트");
product3.setPrice(3000);
product3.setStock(1000);
product3.setProvider(provider);
productRepository3.save(product1);
productRepository3.save(product2);
productRepository3.save(product3);
List<Product> products = providerRepository.findById(provider.getId()).get()
.getProductList();
for(Product product : products){
System.out.println(product);
}
}
Provider 엔티티 클래스는 Product 엔티티와 연관관계에서 주인이 아니기 때문에 외래키 관리 불가
그래서 Provider를 등록한 후 각 Product에 객체를 설정하는 작업을 통해 DB에 저장
ProductList 필드에 Product 엔티티를 추가하는 방식으로 레코드 저장시 Provider 엔티티 클래스는 연관관게의 주인이 아니기에 DB에 반영이 안됨
provider.getProductList.add(product1); // 무시
provider.getProductList.add(product2); // 무시
provider.getProductList.add(product3); // 무시
Hibernate:
select
provider0_.id as id1_2_0_,
provider0_.created_at as created_2_2_0_,
provider0_.updated_at as updated_3_2_0_,
provider0_.name as name4_2_0_,
productlis1_.provider_id as provider7_0_1_,
productlis1_.number as number1_0_1_,
productlis1_.number as number1_0_2_,
productlis1_.created_at as created_2_0_2_,
productlis1_.updated_at as updated_3_0_2_,
productlis1_.name as name4_0_2_,
productlis1_.price as price5_0_2_,
productlis1_.provider_id as provider7_0_2_,
productlis1_.stock as stock6_0_2_,
productdet2_.id as id1_1_3_,
productdet2_.created_at as created_2_1_3_,
productdet2_.updated_at as updated_3_1_3_,
productdet2_.description as descript4_1_3_,
productdet2_.product_number as product_5_1_3_
from
provider provider0_
left outer join
product productlis1_
on provider0_.id=productlis1_.provider_id
left outer join
product_detail productdet2_
on productlis1_.number=productdet2_.product_number
where
provider0_.id=?