N쪽 : 외래키가 있는 쪽으로 = 연관관계의 주인이다.
[테이블] : 항상 N쪽에 외래키가 존재하도록 설계
[객체] : N쪽에 참조할 객체 필드 선언(테이블과 연관관계 매핑)
<객체 연관관계>
Member(Long id, Team team, String username)
Team(Long id, String name)
<테이블 연관관계>
Member(MEMBER_ID(PK), USERNAME, TEAM_ID(FK))
TEAM(TEAM_ID(PK), NAME)
-------객체 Member의 Team team와 테이블 MEMBER의 TEAM_ID가 연관관계 매핑-------
예시) N(Member) : 1(Team)
Member class...
@Id @GeneratedValue //생략하면 AUTO
@Column(name = "MEMBER_ID")
private Long id;
private String username;
@ManyToOne
@JoinColumn(name = "TEAM_ID")
private Team team;
Team class...
@Id
@GeneratedValue
@Column(name = "TEAM_ID")
private Long id;
private String name;
<객체 연관관계>
Member(Long id, Team team, String username)
Team(Long id, String name, List members)
<테이블 연관관계>
Member(MEMBER_ID(PK), USERNAME, TEAM_ID(FK))
TEAM(TEAM_ID(PK), NAME)
-------객체 Member의 Team team와 테이블 MEMBER의 TEAM_ID가 연관관계 매핑-------
예시) N(Member) : 1(Team)
Member class...
@Id @GeneratedValue //생략하면 AUTO
@Column(name = "MEMBER_ID")
private Long id;
private String username;
@ManyToOne
@JoinColumn(name = "TEAM_ID")
private Team team;
Team class...
@Id
@GeneratedValue
@Column(name = "TEAM_ID")
private Long id;
private String name;
@OneToMany(mappedBy = "team")
private List<Member> members = new ArrayList<>();
1쪽 : 연관관계의 주인
N쪽 : (테이블)외래키를 가진다.
JOIN COLUMN을 꼭 1쪽에 작성해주어야 한다.
객체와 테이블이 차이 때문에 반대편 테이블(MEMBER)의 외래키를 관리하는 특이한 구조
<객체 연관관계>
Member(Long id, String username)
Team(Long id, String name, List members)
<테이블 연관관계>
Member(MEMBER_ID(PK), USERNAME, TEAM_ID(FK))
TEAM(TEAM_ID(PK), NAME)
-------객체 Team의 List members와 테이블 MEMBER의 TEAM_ID가 연관관계 매핑-------
예시) N(Member) : 1(Team) .. 1쪽에서 연관관계의 주인으로 설정된다.
Member class...
@Id @GeneratedValue //생략하면 AUTO
@Column(name = "MEMBER_ID")
private Long id;
private String username;
Team class...
@Id
@GeneratedValue
@Column(name = "TEAM_ID")
private Long id;
private String name;
@OneToMany
@JoinColumn(name = "TEAM_ID")
private List<Member> members = new ArrayList<>();
객체의 TEAM(1쪽)과 테이블의 MEMBER의 TEAM_ID와 연관관계 매핑이 된다.
반대편 테이블(MEMBER)의 외래키를 관리하는 특이한 구조가 된다.
-> 일대다 대신, 필요할 경우 다대일 단방향을 다대일 양방향으로 바꾸어서 사용하도록 한다.
공식적으로 이러한 매핑은 존재x
@JoinColumn(insertable = false, updatable = false)
: MEMBER(N쪽)에 매핑이 되는 컬럼에 작성해준다. TEAM과 MEMBER에 모두 @JoinColumn을 작성, 이대로 두면 모두 연관관계 주인이 되지만, MEMBER에는 insertable = false, updatable = false
를 추가해주면 읽기전용이 된다. 따라서 위의 속성을 추가
<객체 연관관계>
Member(Long id, String username, Team team)
Team(Long id, String name, List members)
<테이블 연관관계>
Member(MEMBER_ID(PK), USERNAME, TEAM_ID(FK))
TEAM(TEAM_ID(PK), NAME)
-------객체 Team의 List members와 테이블 MEMBER의 TEAM_ID가 연관관계 매핑-------
예시) N(Member) : 1(Team) .. 1쪽에서 연관관계의 주인으로 설정된다.
Member class...
@Id @GeneratedValue //생략하면 AUTO
@Column(name = "MEMBER_ID")
private Long id;
private String username;
@ManyToOne
@JoinColumn(name = "TEAM_ID", insertable = false, updatable = false) //읽기전용
private Team team;
Team class...
@Id
@GeneratedValue
@Column(name = "TEAM_ID")
private Long id;
private String name;
@OneToMany
@JoinColumn(name = "TEAM_ID")
private List<Member> members = new ArrayList<>();
-> 결론 : 다대일 양방향을 사용
주 테이블에 외래키를 넣거나 or 대상 테이블에 외래키를 넣는 방법이 있다.
외래키에 데이터베이스 유니크 제약조건을 추가되어야 일대일 관계가 된다.
단방향, 양방향인 경우는 다대일 관계와 유사하게 작성하면 된다.
연관관계의 주인이 되는 쪽 : 외래키가 있는 곳
[단방향, 주테이블에 외래키 설정]
가장 단순한 방식은 아래와 같이 설정하면 된다.
<객체 연관관계>
Member(Long id, Locker locker, String username)
Locker(Long id, String name)
<테이블 연관관계>
Member(MEMBER_ID(PK), LOCKER_ID(FK, UNI), USERNAME)
LOCKER(LOCKER_ID(PK), NAME)
-------객체 Member의 Locker locker와 테이블 MEMBER의 LOCKER_ID가 연관관계 매핑-------
예시) 1(Member) : 1(Locker) .. 외래키가 있는 곳을 연관관계의 주인으로 설정된다.
Member class...
@Id @GeneratedValue //생략하면 AUTO
@Column(name = "MEMBER_ID")
private Long id;
private String username;
@ManyToOne
@JoinColumn(name = "TEAM_ID", insertable = false, updatable = false) //읽기전용
private Team team;
@OneToOne
@JoinColumn(name = "LOCKER_ID")
private Locker locker;
Locker class...
@Id @GeneratedValue
@Column(name = "LOCKER_ID")
private Long id;
private String name;
[양방향, 주테이블에 외래키 설정]
<객체 연관관계>
Member(Long id, Locker locker, String username)
Locker(Long id, String name, Member member)
<테이블 연관관계>
Member(MEMBER_ID(PK), LOCKER_ID(FK, UNI), USERNAME)
LOCKER(LOCKER_ID(PK), NAME)
-------객체 Member의 Locker locker와 테이블 MEMBER의 LOCKER_ID가 연관관계 매핑-------
Member class...
@Id @GeneratedValue //생략하면 AUTO
@Column(name = "MEMBER_ID")
private Long id;
private String username;
@ManyToOne
@JoinColumn(name = "TEAM_ID", insertable = false, updatable = false) //읽기전용
private Team team;
@OneToOne
@JoinColumn(name = "LOCKER_ID")
private Locker locker;
Locker class...
@Id @GeneratedValue
@Column(name = "LOCKER_ID")
private Long id;
private String name;
@OneToOne(mappedBy = "locker")
private Member member;
[단방향, 대상 테이블에 외래키 설정]
[양방향, 대상 테이블에 외래키 설정]
<객체 연관관계>
Member(Long id, Locker locker, String username)
Locker(Long id, String name, Member member)
<테이블 연관관계>
Member(MEMBER_ID(PK), USERNAME)
LOCKER(LOCKER_ID(PK), NAME, MEMBER_ID(FK, UNI))
-------객체 Locker의 Member member와 테이블 LOCKER의 MEMBER_ID가 연관관계 매핑-------
[일대일 정리]
연결 테이블을 추가해서 일대다, 다대일 관계로 풀어내야 한다.
객체 2개로 다대다 관계 설정이 가능
연결 테이블용 엔티티를 추가(연결 테이블을 엔티티로 승격)
<객체 연관관계>
Member(Long id, List memberProducts, String username)
Product(Long id, String name)
MemberProduct(Long id, Member member, Product product, int orderAmount, Date orderDate)
<테이블 연관관계>
Member(MEMBER_ID(PK), USERNAME)
Product(LOCKER_ID(PK), NAME)
Order(ORDER_ID(PK), MEMBER_ID(FK), PRODUCT_ID(FK), ORDERAMOUNT, ORDERDATE)
---객체 Member는 MemberProduct에 대해 @OneToMany 관계, 객체 Product는 MemberProduct에 대해 @OneToMany 관계, MemberProduct는 Member와 Product 각각에 대해 @ManyToOne 관계 ----
Member class...
@Id
@GeneratedValue //생략하면 AUTO
@Column(name = "MEMBER_ID")
private Long id;
private String username;
@ManyToOne
@JoinColumn(name = "TEAM_ID", insertable = false, updatable = false) //읽기전용
private Team team;
@OneToOne
@JoinColumn(name = "LOCKER_ID")
private Locker locker;
@OneToMany(mappedBy = "member")
private List<MemberProduct> memberProducts = new ArrayList<>();
Product class...
@Id @GeneratedValue
@Column(name = "PRODUCT_ID")
private Long id;
private String name;
@OneToMany(mappedBy = "product")
private List<MemberProduct> memberProductList;
private int count;
private int price;
private LocalDateTime orderDateTime;
MemberProduct class...
@Id @GeneratedValue
private Long id;
@ManyToOne
@JoinColumn(name= "MEMBER_ID")
private Member member;
@ManyToOne
@JoinColumn(name = "PRODUCT_ID")
private Product product;
[@JoinColumn 속성]
referencedColumnName : 외래키가 참조하는 대상 테이블의 칼럼명(default : 참조하는 대상 테이블의 기본키 칼럼명)
unique, nullable, insertable, updateable, columnDefinition, table : @Column의 속성과 같다.
name : 매핑할 외래키 이름
연관관계의 주인이 되므로 mappedBy 속성이 존재하지 않는다
optional : false로 설정하면 연관된 엔티티가 항상 있어야 한다
(default : true)
fetch : 글로벌 패치 전략을 설정
(default : @ManyToOne = FetchType.EAGER, @OneToMany = FetchType.LAZY)
cascade : 영속성 전이 기능사용
mappedBy : 연관관계의 주인 필드를 가리키는 역할을 한다.
fetch : 글로벌 패치 전략을 설정
(default : @ManyToOne = FetchType.EAGER, @OneToMany = FetchType.LAZY)
cascade : 영속성 전이 기능사용
Member(MEMBER_ID(PK), Name, CITY, STREET, ZIPCODE)
ORDERS(ORDER_ID(PK), MEMBER_ID(FK), DELIVERY_ID(FK), ORDERDATE, STATUS)
DELIVERY(DELIVERY_ID(PK), CITY, STREET, ZIPCODE, STATUS)
CATEGORY(CATEGORY_ID(PK), PARENT_ID(FK), NAME)
CATEGORY_ITEM(CATEGORY_ID(FK), ITEM_ID(FK) (PK))
ITEM(ITEM_ID, NAME, PRICE, STOCKQUANTITY)
ORDER_ITEM(ORDER_ITEM_ID(PK), ORDER_ID(FK), ITEM_ID(FK), ORDERPRICE, COUNT)
Member(Long id, String name, String city, String street, String zipcode, List orders)
Order(Long id, Member member, List orderItems, Delivery delivery, Date orderDate, OrderStatus status)
Delivery(Long id, Order order, String city, String street, String zipcode, DeliveryStatus status)
Category(Long id, String name, List items, Category parent, List child)
Item(Long id, String name, int price, int stockQuantity, List categories)
OrderItem(Long id, Item item, Order order, int orderPrice, int count)
Delivery class...
@Id
@GeneratedValue
@Column(name = "DELIVERY_ID")
private Long id;
@OneToOne(mappedBy = "delivery")
private Orders orders;
Orders class...
@Id
@GeneratedValue
@Column(name = "ORDERS_ID")
private Long id;
@OneToOne
@JoinColumn(name = "DELIVERY_ID")
private Delivery delivery;
private LocalDateTime orderDate;
private String status;
Category class...
@Id
@GeneratedValue
@Column(name = "CATEGORY_ID")
private Long id;
private String name;
@ManyToOne
@JoinColumn(name = "PARENT_ID")
private Category parent;
@OneToMany(mappedBy = "parent")
private List<Category> child = new ArrayList<>();
@ManyToMany
@JoinTable(name = "CATEGORY_ITEM",
joinColumns = @JoinColumn(name = "CATEGORY_ID"),
inverseJoinColumns = @JoinColumn(name = "ITEM_ID"))
private List<Item> items = new ArrayList<>();