티스토리 뷰
1. 코스 테이블과 리뷰 테이블 두개의 관계를 가지고 설명한다.
2. 코스와 리뷰는 One To Many의 관계를 가진다.
3. 코스가 삭제되면 리뷰 역시 삭제되어야 한다.
4. 아래는 데이터베이스 구조 도식이다.
4-1 review 테이블이 추가되었고
4-2 review 테이블의 course_id가 foreign key로 설정되어 있다.
2. One to Many uni-directional은 전의 one-to-one과 one-to-many와는 좀 다르다.
2-1 uni-directional의 방향이 foreign key가 있는 테이블에서 시작하는 경우는 설정이 동일하다.
2-1-1 해당 Entity에 관계하는 Entity의 속성을 추가하고 @Many-To-One과 @JoinColumn을 붙이면 된다.
2-1-2 결국 One-To-One의 uni-directional과 동일한데
2-1-2-1 이것은 테이블 설정이 동일하고 필요에 따라 many, one이 결정되기 때문이다.
2-2 uni-direction의 방향이 반대인 경우는 좀 달라진다. (과정 Entity만 리뷰 정보를 가지는 경우)
2-2-0 이 포스팅이 이 부분에 관한 내용이다.
2-2-1 달라봤자 거기서 거기다.
2-2-2 중요한 것은 @JoinColumn이라는 것의 의미인데
2-2-2-1 관계가 있는 테이블과 join에 필요한 foreign key column을 명시하는 것이다.
2-2-2-2 그러니 A테이블에 있던 B테이블에 있던 상관이 없다.
2-2-2-3 사실 @JoinColumn이 없어도 동작한다. 하지만 명시하는 게 명확하다.
2-2-3 @JoinColumn을 foreign key가 없는 Entity에 붙여준다. 여기서는 Course Entity의 reviews 속성이다.
2-2-3-1 이게 가능한 이유는 속성에 이미 Entity type이 지정되어 있기 때문이다.
2-2-3-1-1 지정된 entity와 매핑되어 있는 테이블의 foreign key를 찾아가게 된다.
2-2-4 간단하게 말하면 direction설정에 foreign key가 있는 Entity가 참여하는 경우는 그 Entity에
2-2-5 참여하지 않는 경우에 상대 Entity에 @JoinColumn을 붙인다.
2-2-6 아래 Review Entity는 uni-direction이기 때문에 lombok으로 인한 recursive가 없으므로 @Data를 사용했다.
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.Table;
import lombok.Data;
import lombok.NoArgsConstructor;
@Entity
@Table(name = "review")
@Data
@NoArgsConstructor
public class Review {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
@Column
private String comment;
public Review(String comment) {
this.comment = comment;
}
}
// 수정된 Course Entity class
@Entity
@Table(name = "course")
@Getter
@Setter
@NoArgsConstructor
public class Course {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
@Column
private String title;
@ManyToOne(cascade = { CascadeType.DETACH,
CascadeType.MERGE, CascadeType.PERSIST,CascadeType.REFRESH })
@JoinColumn(name = "instructor_id")
private Instructor instructor;
@OneToMany(cascade = CascadeType.ALL)
@JoinColumn(name = "course_id")
private List<Review> reviews;
public Course(String title) {
this.title = title;
}
@Override
public String toString() {
return "Course [id=" + id + ", title=" + title + "]";
}
public void addReview(Review review) {
if (this.reviews == null) {
this.reviews = new ArrayList<>();
}
this.reviews.add(review);
}
}
3. 데이터를 저장하는 코드이다.
3-1 @JoinTable이 지정된 course를 저장하는 것이므로 자동으로 foreign키를 참조하고 저장한다.
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.cfg.Configuration;
import pe.pilseong.hibernate_mapping.entities.Course;
import pe.pilseong.hibernate_mapping.entities.Instructor;
import pe.pilseong.hibernate_mapping.entities.InstructorDetail;
import pe.pilseong.hibernate_mapping.entities.Review;
public class SaveEntity {
public static void main(String[] args) {
SessionFactory factory = new Configuration().configure()
.addAnnotatedClass(Instructor.class)
.addAnnotatedClass(InstructorDetail.class)
.addAnnotatedClass(Course.class)
.addAnnotatedClass(Review.class)
.buildSessionFactory();
Review review1 = new Review("Best course ever!!!");
Review review2 = new Review("Mediocre course ever!!!");
Review review3 = new Review("Worst course ever!!!");
Session session = factory.getCurrentSession();
try {
session.beginTransaction();
Course course = session.get(Course.class, 2L);
course.addReview(review1);
course.addReview(review2);
course.addReview(review3);
session.save(course);
session.getTransaction().commit();
session = factory.getCurrentSession();
session.beginTransaction();
course = session.get(Course.class, 2L);
System.out.println("Course :: " + course.toString());
course.getReviews().stream().forEach(System.out::println);
session.getTransaction().commit();
} catch (Exception e) {
e.printStackTrace();
} finally {
session.close();
factory.close();
}
}
}
4. Course를 가지고 오는 예제
public class FetchEntity {
public static void main(String[] args) {
SessionFactory factory = new Configuration().configure()
.addAnnotatedClass(Instructor.class)
.addAnnotatedClass(InstructorDetail.class)
.addAnnotatedClass(Course.class)
.addAnnotatedClass(Review.class)
.buildSessionFactory();
Session session = factory.getCurrentSession();
try {
session.beginTransaction();
Course course = session.get(Course.class, 2L);
System.out.println("Fetchd course :: " + course.toString());
course.getReviews().stream().forEach(System.out::println);
session.getTransaction().commit();
} catch (Exception e) {
e.printStackTrace();
} finally {
session.close();
factory.close();
}
}
}
// 결과
Fetchd course :: Course [id=2, title=Spring Boot intermediate]
Review(id=1, comment=Best course ever!!!)
Review(id=2, comment=Mediocre course ever!!!)
Review(id=3, comment=Worst course ever!!!)
5. 삭제 예제 이다.
5-1 첫번 째는 하나의 Review만 삭제한 것이고 comment 달아 놨다.
5-2 두번 째는 course를 지우니 관련된 review가 다 지워지는지 테스트 한다.
public class DeleteEntity {
public static void main(String[] args) {
SessionFactory factory = new Configuration().configure()
.addAnnotatedClass(Instructor.class)
.addAnnotatedClass(InstructorDetail.class)
.addAnnotatedClass(Course.class)
.addAnnotatedClass(Review.class)
.buildSessionFactory();
Session session = factory.getCurrentSession();
try {
session.beginTransaction();
// Review review = session.get(Review.class, 1L);
// System.out.println("Fetched Review :: " + review.toString());
//
// session.delete(review);
Course course = session.get(Course.class, 2L);
System.out.println("Fetchd course :: " + course.toString());
course.getReviews().stream().forEach(System.out::println);
session.delete(course);
session.getTransaction().commit();
} catch (Exception e) {
e.printStackTrace();
} finally {
session.close();
factory.close();
}
}
}
// 결과 - 첫번째
Fetched Review :: Review(id=1, comment=Best course ever!!!)
Hibernate: delete from review where id=?
// 결과 - 두번째
Fetchd course :: Course [id=2, title=Spring Boot intermediate]
Review(id=2, comment=Mediocre course ever!!!)
Review(id=3, comment=Worst course ever!!!)
Hibernate: update review set course_id=null where course_id=?
Hibernate: delete from review where id=?
Hibernate: delete from review where id=?
Hibernate: delete from course where id=?
6. 솔직히 존나 복잡해 보인다.
6-1 필요하면 공식 doc을 참조하길 바란다.
6-2 요약하면 아래와 같다. 위의 doc에 있는 그대로 영어로 복사했다.
(Optional) The name of the foreign key column. The table in which it is found depends upon the context.
- If the join is for a OneToOne or ManyToOne mapping using a foreign key mapping strategy, the foreign key column is in the table of the source entity or embeddable.
- If the join is for a unidirectional OneToMany mapping using a foreign key mapping strategy, the foreign key is in the table of the target entity.
- If the join is for a ManyToMany mapping or for a OneToOne or bidirectional ManyToOne/OneToMany mapping using a join table, the foreign key is in a join table.
- If the join is for an element collection, the foreign key is in a collection table.
'Spring > Hibernate' 카테고리의 다른 글
Hibernate : Many-To-Many Mapping - Part 2 (0) | 2020.05.08 |
---|---|
Hibernate : Many-To-Many Mapping - Part 1 (0) | 2020.05.07 |
Hibernate : Lazy and Eager Loading (0) | 2020.05.07 |
Hibernate : One-To-Many Mapping Bi-Directional (0) | 2020.05.06 |
Hibernate : One-To-One Mapping Bi-Directional (0) | 2020.05.06 |
- Total
- Today
- Yesterday
- 도커 개발환경 참고
- AWS ARN 구조
- Immuability에 관한 설명
- 자바스크립트 멀티 비동기 함수 호출 참고
- WSDL 참고
- SOAP 컨슈머 참고
- MySql dump 사용법
- AWS Lambda with Addon
- NFC 드라이버 linux 설치
- electron IPC
- mifare classic 강의
- go module 관련 상세한 정보
- C 메모리 찍어보기
- C++ Addon 마이그레이션
- JAX WS Header 관련 stackoverflow
- SOAP Custom Header 설정 참고
- SOAP Custom Header
- SOAP BindingProvider
- dispatcher 사용하여 설정
- vagrant kvm으로 사용하기
- git fork, pull request to the …
- vagrant libvirt bridge network
- python, js의 async, await의 차이
- go JSON struct 생성
- Netflix Kinesis 활용 분석
- docker credential problem
- private subnet에서 outbound IP 확…
- 안드로이드 coroutine
- kotlin with, apply, also 등
- 안드로이드 초기로딩이 안되는 경우
- navigation 데이터 보내기
- 레이스 컨디션 navController
- raylib
- Spring
- Validation
- 외부파일
- 스프링
- 설정하기
- MYSQL
- hibernate
- Rest
- RestTemplate
- Security
- Angular
- login
- 매핑
- 상속
- spring boot
- Many-To-Many
- XML
- mapping
- Spring Security
- WebMvc
- one-to-many
- form
- 로그인
- crud
- 스프링부트
- 하이버네이트
- 설정
- one-to-one
- 자바
- jsp