@ManyToMany 어노테이션은 N 대 M 관계를 맺어준다.
N:M 관계에서는 중간 테이블이 필요하다.
중간 테이블의 이름을 orders, 조인할 컬럼을 food_id, user_id로 설정하면 다음과 같다
@Entity
@Table(name = "food")
public class Food {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
private String name;
private double price;
@ManyToMany
@JoinTable(name = "orders", // create orders table
joinColumns = @JoinColumn(name = "food_id"), // Food Entity's join column
inverseJoinColumns = @JoinColumn(name = "user_id")) // User Entity's join column
private List<User> userList = new ArrayList<>();
}
다만, 생성되는 중간 테이블을 컨트롤하기 어렵기 때문에 중간 테이블 변경시 문제 발생의 위험이 있다.
@Entity
@Table(name = "food")
public class Food {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
private String name;
private double price;
@ManyToMany
@JoinTable(name = "orders", // create orders table
joinColumns = @JoinColumn(name = "food_id"), // Food Entity's join column
inverseJoinColumns = @JoinColumn(name = "user_id")) // User Entity's join column
private List<User> userList = new ArrayList<>();
}
@Entity
@Table(name = "users")
public class User {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
private String name;
@ManyToMany(mappedBy = "userList")
private List<Food> foodList = new ArrayList<>();
}
고객 Entity에 @ManyToMany로 연결하고, mappedBy 옵션으로 외래 키의 주인을 설정하면 양방향 관계가 가능하다.
위의 경우 중간테이블을 간접적으로 생성했지만, 직접 생성하면 변경 발생시 컨트롤이 쉬워 확장성에 좋다.
@Entity
@Table(name = "food")
public class Food {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
private String name;
private double price;
@OneToMany(mappedBy = "food")
private List<Order> orderList = new ArrayList<>();
}
@Entity
@Table(name = "users")
public class User {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
private String name;
@OneToMany(mappedBy = "user")
private List<Order> orderList = new ArrayList<>();
}
@Entity
@Table(name = "orders")
@EntityListeners(AuditingEntityListener.class) //main에 EnableJpaAuditing
public class Order {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
@ManyToOne
@JoinColumn(name = "food_id")
private Food food;
@ManyToOne
@JoinColumn(name = "user_id")
private User user;
@CreatedDate
@Temporal(TemporalType.TIMESTAMP)
private LocalDateTime orderDate;
}
이 경우 중간 테이블이 오래키를 모두 소지하고, 음식, 고객이 접근하는 형식으로 바뀐다.