티스토리 뷰
a. 객체 설계 단계에서는 단방향 연관관계로 끝내야 한다.
- 단방향으로만으로도 관계 매핑이 완료된거임 → 양뱡향으로 해버리면 객체 입장에서 고려할것이 많아짐
- 양방향은 사실 단방향의 2개일 뿐
- 테이블 설계하면서 객체 설계 같이 진행할 것 → 이미 테이블간의 관계는 이미 정해짐
- 무엇이 1:1 관계이고, 1:N 관계인지 N:M 관계인지는 테이블 설계하면서 나올것임 이때 → 외래키를 갖고 있는 객체가 주인으로 단방향 연관관계 맺으면 됌
- 다중성이 헷갈릴때에는 반대로 생각해보기
- 다중성 : @ManyToMany 인지, @OneToMany인지..
- 실무에서 다대다는 지양해야함!
- 양방향은 언제 ?
- 설계 단계에선 하지 않음, 실무하다가 정말 필요하다 생각되면 그 때 추가하면 된다.
- 테이블 수정할 필요도 없고! (테이블 영향도 없음) mappedBy 관계 맺으면 끝
- 단, 양방향하게 되면 무한호출 조심
- 무한호출을 야기하는 toString()이나 JSON 변환을 하지 않기
- 또한 양방향 관계시, 연관관계 편의 메서드 필요하면 생성
- 두개의 테이블에서 공통된 컬럼 값 업데이트를 일일히 하지 않고, 메서드 생성하여 두개의 컬럼 모두 업데이트!
- Order 1 : OrderItem N 관계에서 order.getOrderItem 필요한 경우에 양방향 하면 되는데
- orderItem.findByOrder() 이렇게 find 한번 하는게 나을 수 있음
- 최대한 양방향 피할수있으면 피하기 (고려해야할게 많아지기 때문에)
- 설계 단계에선 하지 않음, 실무하다가 정말 필요하다 생각되면 그 때 추가하면 된다.
b. 양방향 매핑 규칙
- 2관계중 외래키가 있는곳으로 주인으로 하여, 관계중 주인을 정해야 한다.
- 주인이 아니면 읽기만 가능, mappedBy 속성으로 주인을 지정해줘야함
// order : orderItem 1:N 관계
@Entity
@Table (name ="`order`")
@AllArgsConstructor
@NoArgsConstructor(access = AccessLevel.PROTECTED)
@Getter
public class Order{
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long order_id;
// OrderItem 엔티티에 Order 엔티티 부르는 변수명을 mappedBy 해줘야함
@OneToMany(mappedBy = "order")
private List<OrderItem> orderItem = new ArrayList<>();
}
@Entity
@Table (name ="order_item")
@AllArgsConstructor
@NoArgsConstructor(access = AccessLevel.PROTECTED)
@Getter
public class OrderItem{
...
@ManyToOne
@JoinColumn (name = "order_id") //외래키 컬럼
private Order order;
}
c. 영속성 컨텍스트
- 영속성 컨텍스트를 이해해야 실제 JPA가 어떻게 작동하는지 알 수 있다.
- API 요청에 따라 EntityManagerFactory 는 EntityManager 생성
- EntityManager.persist(entity);
- DB 저장이 아닌, 영속성 컨텍스트에 저장을 하겠다.
- 엔티티 매니저를 통해서 영속성 컨텍스트에 접근!
- 영속상태
- em.persist() 한 상태
- 객체를 저장하여서 , 영속성 컨텍스트가 관리하는 상태 ⇒ But 아직 DB 저장 전
- 비영속상태
- 객체 생성만 한 상태
- 트랜잭션 커밋 했을때 영속성 컨텍스트안에 있는 쿼리 날림
- JPA 는 영속성컨텍스트 덕분에 조금이나마 효율! → SQL 을 모아서 보내기 때문에
- 마이바티스는 DB 로 바로 쿼리 보냄
- 효율이 있긴 하나, 크진 않음 → 영속성 컨텍스트가 트랜잭션 커밋을 할때 DB에 보내고 비워지기에, 하나의 트랜잭션안의 쿼리만 같이 DB 에 전송하는것이기 때문이다 (많은 처리를 하는 API 의 경우는 도움됌)
Member member = new Member(); // 비영속상태
member.setName("haha");
em.persist(member); // 영속상태 -> 이때 save 쿼리 안나감 / 커밋될때 나감
String whatName = member.getName(); // 영컨에서 값 가져오는것
c-1. 트랜잭션 커밋될때, 영속성컨텍스트 동작 과정
- flush() 호출
- Entity 와 스냅샷 비교
- 스냅샷: DB 에서 가져와서 1차 캐시한 엔티티
- 바뀐 값에 대해 Update query 쓰기지연SQL 저장소에 저장
- flush() : SQL query 디비에 전송
- Commit
e. flush()
- flush() 가 하는일
- 변경감지 (더티체킹)
- 수정된 엔티티를 쓰기 지연 SQL 저장소에 등록
- 쓰기 지연소 SQL 저장소의 쿼리를 데이터베이스에 전송한다.
- flush() 가 호출되는 순간 : 영속성 컨텍스트의 변경 내용 즉시 DB 반영
- em.flush() : 직접호출하는 방법 (사용할 일 없음/ 테스트할때 사용)
- transaction commit : flush 자동호출
- JPQL 쿼리 실행 : flush 자동호출
- JPQL 쿼리 실행되기전에 flush 한 후에 JPQL 쿼리 실행
- flush() 되어도 영속성 컨텍스트가 비워져도 1차 캐시는 값 유효하다.
Member firstMemeber = new Member();
firstMember.setName("ha");
memberRepository.save(firstMemeber);
em.flush(); //flush()를 해도 영속성 컨텍스트에 1차 캐시 값은 남아있다.
System.out.println(firstMember.getName) //영속성 컨텍스트에서 캐시 값 가져오는거 -> DB 조회 안함
'spring' 카테고리의 다른 글
Spring AOP 가 필요한 경우, 무엇인가, 관련 용어 (0) | 2025.04.15 |
---|---|
@Column(updateable = false) 작동 확인 (0) | 2025.02.14 |
Redis +Spring Cache 조회했을때 성능비교 (2) | 2025.02.14 |
M:N 다대다 연관 관계 (0) | 2025.02.10 |
spring 초기 셋팅,프로젝트 jdk설정 (0) | 2021.12.27 |
공지사항
최근에 올라온 글
최근에 달린 댓글
- Total
- Today
- Yesterday
링크
TAG
- 파이썬기초
- 스프링
- eclipse
- sourcetree
- UML
- 기초100제
- JPA
- 객체지향모델링
- 개인프로젝트
- 모델링
- java
- set
- 레이아웃
- Spring
- 자바기초
- sql
- 객체지향
- web
- 코딩
- 유스케이스
- 깃
- 백엔드
- 코드업기초
- 이클립스
- 안드로이드
- 파이썬
- laravel
- 자바
- 다이어그램
- 코드업
일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | |||||
3 | 4 | 5 | 6 | 7 | 8 | 9 |
10 | 11 | 12 | 13 | 14 | 15 | 16 |
17 | 18 | 19 | 20 | 21 | 22 | 23 |
24 | 25 | 26 | 27 | 28 | 29 | 30 |
31 |
글 보관함