[JPA] 연관관계
- - 클래스 멤버변수로 다른 클래스를 가지고 싶을 때 JPA에서는 id대신 그 객체 자체를 멤버로 가지고 그걸 @OneToOne .. 으로 설정하면 자동으로 연관관계가 만들어진다.
- - ERD에 없어도 양방향으로 @~to~를 달아준다. =>실제 db에서는 소유한 클래스의 id가 필드로 추가된다.
ㄴ optional = : 해당 클래스는 null값을 가질 수 없다.
ㄴ mappedBy=”” 주인이 아닌 클래스에서 역으로 주인을 참조할 때. 속성값으로 자기 자신을 적어준다(?), 이걸 하면 주인 클래스는 컬럼에 추가되지 않는다.(주인 클래스를 소유하지 않았으므로)
ㄴ 1. FK가 있는 곳을 주인으로 한다.
2. 객체의 개념에 따라서 Book에도 BookReviewInfo를 추가하고, BookReviewInfo에도 Book을 추가하는 식으로 양쪽 다 삽입하는 것도 실수를 줄이기 위한 방법이다.
3. 설계는 단방향(bookReviewInfo->Book)으로 하되, 반대로 접근이 필요해진 곳(Book->BookReviewInfo)에 양방향을 추가하는 식으로 코드를 작성한다.
ㄴ 양방향으로 서로를 멤버로 가지면 toString의 순환참조가 발생하기 때문에 오류발생
=> @toString.Exclude를 해줘야 한다.
- Many쪽에 FK를 가지고 주인이 되는듯..? => 이쪽에서 one을 조작 / oneToOne은 상황보고 주인을 지정하면 될 듯..?
OneToMany
@OneToMany(fetch = FetchType.EAGER)
@ToString.Exclude
@JoinColumn(name="user_id",insertable = false,updatable = false)
//user를 통해서 생성,update되면 안된다.(listener 통해서만 가능)
private List<UserHistory> userHistories=new ArrayList<>();
- postperist하기 전에는 null이기 때문에 로직에 따라 null포인트 오류가 일어날 수 있으므로 기본생성자로 생성
- @JoinColum : @OneToMany일때 필요. History가서 user_id컬럼을 만들어서(이미 있으면 그걸로 함) 지금 여기 id를 join시켜 두 테이블 매핑. (안하면 user-userHistory테이블이 또 만들어짐)
- name을 지정해주지 않으면 user_histories_id의 형태로 history 테이블에 저장됨
- history에서 속성명이 같은 이름의 카멜케이스로 되어있다면 이 컬럼명은 스네이크 케이스고, 그 스네이크 케이스이름을 joinColumn으로 지정하면 충돌이 생김
=> history의 컬럼명을 스네이크케이스로 지정한다. :@Column(name="")
- UserHistory에서 User를 @ManyToOne으로 지정하면 user_id가 만들어지므로 history에서 지정안해줘도 됨
@ManyToMany
: 잘 안씀, many를 one으로 묶어 manyToOne으로 처리하는 경우가 더 많음. .꼭 필요할 때만 쓰도록
public void addAuthors(Author... authors){
Collections.addAll(this.authors,authors)
}
- … : 배열 표시 => 컴마로 구분해서 매개변수로 넣어주면 배열로 처리됨
- Collections.addAll(c, elements) => 콜렉션타입 c에 elements를 모두 add
- oneto: many쪽에서만 one을 등록해주면 one쪽에서는 자동으로 연결됐었는데 여기선 서로 등록해줘야 함.
: many쪽에 one의 아이디 필드가 있으므로써 중간테이블을 생략할 수 있었는데, manyTOMany는 어느쪽에 아이디필드가(fk)있어야 하는지 모호하기 때문에 그냥 중간테이블 생성. 생략불가능하다.
- 두 테이블 사이 중간테이블을 만들어서 ManyToOne/OneToMany로 바꿀 수 있다. 관계테이블에 두 객체 관계를 넣고, 두 테이블에도 관계를 넣어준다.