데이터베이스에서 테이블끼리 외래키를 통해 연관관계를 맺듯이 엔티티끼리 연관 관계를 매핑해서 사용한다
엔티티들은 대부분 다른 엔티티와 연관 관계를 맺고 있다.
JPA에서는 엔티티에 연관관계를 매핑해두고 필요할 때 해당 엔티티와 연관된 엔티티를 사용하여 좀 더 객체지향적으로 프로그래밍 할 수 있다.
-단방향
-양방향
회원엔티티는 앞에서 만들었기 때문에 장바구니(Cart) 엔티티를 만들고 회원 엔티티와 연관관계 매핑을 설정.
import javax.persistence.*;
import lombok.Data;
@Entity
@Table(name="cart")
@Data
public class Cart {
@Id
@Column(name = "cart_id")
@GeneratedValue(strategy=GenerationType.AUTO)
private Long id;
@OneToOne
@JoinColumn(name="user_id")
private Users users;
}
장바구니 엔티티가 일방적으로 회원 엔티티를 참조
장바구니와 회원은 일대일로 매핑돼 있으며, 장바구니 엔티티가 회원 엔티티를 참조하는 일대일 단방향 매핑이다.
Cart테이블은 user_id를 외래키(foreign key) 가지고 있다.
테이블을 먼저 생성하는 쿼리문이 실행되고 user_id를 foreign key로 지정하는 쿼리문이 실행한다.
실제로 장바구니 Cart엔티티를 조회하면 user_id를 가지고온다.
CartRepository.java
public interface CartRepository extends JpaRepository<Cart, Long> {
}
package com.shopping.study.entity 패키지에 CartTest생성
em.flush()
em.clear()
package com.shopping.study.entity;
import static org.junit.jupiter.api.Assertions.assertEquals;
import javax.persistence.EntityManager;
import javax.persistence.EntityNotFoundException;
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.security.crypto.password.PasswordEncoder;
import org.springframework.test.context.TestPropertySource;
import org.springframework.transaction.annotation.Transactional;
import com.shopping.study.dto.UsersFormDto;
import com.shopping.study.repository.CartRepository;
import com.shopping.study.repository.UsersRepository;
@SpringBootTest
@Transactional
@TestPropertySource(locations="classpath:application-test.properties")
public class CartTest {
@Autowired
CartRepository cartRepository;
@Autowired
UsersRepository usersRepository;
@Autowired
PasswordEncoder passwordEncoder;
@Autowired
EntityManager em;
public Users createUsers() {
UsersFormDto usersFormDto = new UsersFormDto();
usersFormDto.setEmail("angela@naver.com");
usersFormDto.setName("안젤");
usersFormDto.setAddress("대한민국");
usersFormDto.setPassword("1234");
return Users.createUser(usersFormDto, passwordEncoder);
}
@Test
@DisplayName("장바구니 회원 엔티티 매핑 테스트 ")
public void findCartAndUsersTest() {
Users users = createUsers();
usersRepository.save(users);
Cart cart = new Cart();
cart.setUsers(users);
cartRepository.save(cart);
em.flush();
em.clear();
Cart savedCart = cartRepository.findById(cart.getId()).orElseThrow(EntityNotFoundException::new);
assertEquals(savedCart.getUsers().getId(), users.getId());
}
}
테스트 성공후 콘솔창에
cart아래에 users도 같이 들고오는걸 확인할 수 있다.
📍 여기서 잠깐
엔티티를 조회할 때 해당 엔티티와 매핑된 엔티티도 한 번에 조회하는것을즉시 로딩
이라고 한다.
일대일(OneToOne), 다대일(ManyToOne)로 매핑할 경우 즉시 로딩을 기본 Fetch 전략을 설정한다. Cart.java클래스에서 users엔티티와 일대일 매핑 관계를 맺어줄 때 따로 옵션을 주지 않으면 아래코드와 같이 FetchType.EAGER(즉시 로딩)로 설정하는것과 동일하다.
@OneToOne(fetch = FetchType.EAGER)