DB에서 정보를 가진 Table들은 연관관계를 지님.

두 테이블에서 주문을 받을때 저장이 되야하는 곳은 어디인가?
고객 테이블

음식 테이블


고객정보와 음식정보를 합치는 중간 테이블인 주문 테이블을 생성하여 연관관계를 해결.

고객 1명은 주문을 여러번 할 수 있다.
음식 1개는 주문이 여러번 될 수 있다.
단방향 : 하나의 테이블에서만 참조가 가능.
양방향 : 서로 연관관계를 가지는 테이블끼리 참조가 가능.
DB에서는 JOIN을 통해 서로의 데이터를 확인하고 검증이 가능하기에 방향성이 존재하지않는다.

@Entity
@Table(name = "food")
public class Food {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
private String name;
private double price;
@ManyToOne
@JoinColumn(name = "user_id")
private User user;
}
@Entity
@Table(name = "users")
public class User {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
private String name;
@OneToMany(mappedBy = "user")
private List<Food> foodList = new ArrayList<>();
}
2개의 Entity가 서로의 객체에대한 정보를 지닐수 있는 공간을 가지고있음.
DB는 JOIN을 통해 서로의 정보를 조회가 가능하지만.
JPA 내에서는 실질적인 정보객체를 지니지않는다면 그 정보를 참조할수있는 방법이 존재하지않음.
DB내에 실제 컬럼으로서는 존재하지않지만 Entity를 참조하기위해 사용한다.
List를 가지는 이유는 N의 관계를 표현하기위해서.

(해당사진의 user_id 중첩에 대한 방법)
단방향 관계
@Entity
@Table(name = "food")
public class Food {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
private String name;
private double price;
@ManyToOne
@JoinColumn(name = "user_id")
private User user;
}
@Entity
@Table(name = "users")
public class User {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
private String name;
}
@JoinColumn() 을 통해 외래키의 주인 지정가능@OneToOne 어노테이션을 통해 관계지정
@Entity
@Table(name = "food")
public class Food {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
private String name;
private double price;
@OneToOne
@JoinColumn(name = "user_id")
private User user;
}
@Entity
@Table(name = "users")
public class User {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
private String name;
}

@Entity
@Table(name = "food")
public class Food {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
private String name;
private double price;
@OneToOne
@JoinColumn(name = "user_id")
private User user;
}
@Entity
@Table(name = "users")
public class User {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
private String name;
@OneToOne(mappedBy = "user")
private Food food;
}
mappedBy 옵션을 통해 설정 @Test
@Rollback(value = false) // 테스트에서는 @Transactional 에 의해 자동 rollback 됨으로 false 설정해준다.
@DisplayName("1대1 단방향 테스트")
void test1() {
User user = new User();
user.setName("Robbie");
// 외래 키의 주인인 Food Entity user 필드에 user 객체를 추가해 줍니다.
Food food = new Food();
food.setName("후라이드 치킨");
food.setPrice(15000);
food.setUser(user); // 외래 키(연관 관계) 설정
userRepository.save(user);
foodRepository.save(food);
}
@Test
@DisplayName("1대1 조회 : Food 기준 user 정보 조회")
void test5() {
Food food = foodRepository.findById(1L).orElseThrow(NullPointerException::new);
// 음식 정보 조회
System.out.println("food.getName() = " + food.getName());
// 음식을 주문한 고객 정보 조회
System.out.println("food.getUser().getName() = " + food.getUser().getName());
}
@Test
@DisplayName("1대1 조회 : User 기준 food 정보 조회")
void test6() {
User user = userRepository.findById(1L).orElseThrow(NullPointerException::new);
// 고객 정보 조회
System.out.println("user.getName() = " + user.getName());
// 해당 고객이 주문한 음식 정보 조회
Food food = user.getFood();
System.out.println("food.getName() = " + food.getName());
System.out.println("food.getPrice() = " + food.getPrice());
}
@ManyToOne 을 통해 관계를 맺어준다.
@Entity
@Table(name = "food")
public class Food {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
private String name;
private double price;
@ManyToOne
@JoinColumn(name = "user_id")
private User user;
}
@Entity
@Table(name = "users")
public class User {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
private String name;
}

@Entity
@Table(name = "food")
public class Food {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
private String name;
private double price;
@ManyToOne
@JoinColumn(name = "user_id")
private User user;
}
@Entity
@Table(name = "users")
public class User {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
private String name;
@OneToMany(mappedBy = "user")
private List<Food> foodList = new ArrayList<>();
}
@Test
@DisplayName("N대1 조회 : Food 기준 user 정보 조회")
void test5() {
Food food = foodRepository.findById(1L).orElseThrow(NullPointerException::new);
// 음식 정보 조회
System.out.println("food.getName() = " + food.getName());
// 음식을 주문한 고객 정보 조회
System.out.println("food.getUser().getName() = " + food.getUser().getName());
}
@Test
@DisplayName("N대1 조회 : User 기준 food 정보 조회")
void test6() {
User user = userRepository.findById(1L).orElseThrow(NullPointerException::new);
// 고객 정보 조회
System.out.println("user.getName() = " + user.getName());
// 해당 고객이 주문한 음식 정보 조회
List<Food> foodList = user.getFoodList();
for (Food food : foodList) {
System.out.println("food.getName() = " + food.getName());
System.out.println("food.getPrice() = " + food.getPrice());
}
}
@OneToMany 를 활용하여 관계를 표현.
@Entity
@Table(name = "food")
public class Food {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
private String name;
private double price;
@OneToMany
@JoinColumn(name = "food_id") // users 테이블에 food_id 컬럼
private List<User> userList = new ArrayList<>();
}
@Entity
@Table(name = "users")
public class User {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
private String name;
}

@ManyToOne 의 어노테이션이 mappedBy 옵션을 지원하지 않음.@Entity
@Table(name = "users")
public class User {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
private String name;
@ManyToOne
@JoinColumn(name = "food_id", insertable = false, updatable = false)
private Food food;
}
@Test
@DisplayName("1대N 조회 테스트")
void test2() {
Food food = foodRepository.findById(1L).orElseThrow(NullPointerException::new);
System.out.println("food.getName() = " + food.getName());
// 해당 음식을 주문한 고객 정보 조회
List<User> userList = food.getUserList();
for (User user : userList) {
System.out.println("user.getName() = " + user.getName());
}
}