2023. 2. 3. 16:49ㆍJPA
2/3
* Entity를 만들때 객체를 타입으로 갖기 위해서는 @Embeddible 해줘야 한다.
@Embeddible
@Embeddied
@ManyToOne
@OneToMany
@JoinColumn (fk) 주인
mappedBy( 주인에서 정한 컬럼명)
@Enumrated
* 맵핑 연관관계 주인
다대일 관계에서 다에 fk
일대일에서는 어디에 fk를 둬도 상관 X (직접 조회하는 곳에다 둠)
다대다 상황에서 RDB는 객체끼리 연결이 불가능하기 때문에 중간에 징검다리 역할을 해줄 애를 놔둔다. (실무 X)
fk가 있는 쪽 -> 주인
*엔티티 설계시 주의점
모든 연관관계는 지연로딩으로 설정!
즉시로딩( EAGER )은 예측이 어렵고, 어떤 SQL이 실행될지 추적하기 어렵다.
특히 JPQL을 실행할 때 N+1 문제가 자주 발생한다.
실무에서 모든 연관관계는 지연로딩( LAZY )으로 설정해야 한다.
연관된 엔티티를 함께 DB에서 조회해야 하면, fetch join 또는 엔티티 그래프 기능을 사용한다.
@XToOne(OneToOne, ManyToOne) 관계는 기본이 즉시로딩이므로 직접 지연로딩으로 설정해야 한다.
----> (fetch = FetchType.LAZY)
* 컬렉션은 필드에서 초기화 하자.
옵션
cascade = CascadeType.ALL
예를들어
원래는
OrderItemA
OrderItemB
OrderItemC
Order
이런식으로 별도로 해야 되는걸 Order 로 줄여줌 , 알아서 영속성을 가지게해준다 ?
연관관계 편의 메서드 (양방향 연관관계에서 컨트롤 하는 쪽)
//==연관관계 편의 메서드 ==//
public void setMember(Member member){
this.member = member;
member.getOrders().add(this);
}
public void addOrderItem(OrderItem orderItem) {
orderItems.add(orderItem);
orderItem.setOrder(this);
}
em.persist( ) ->영속성 컨테스트에 객체를 올려놓는다.
pk가 key가된다.
db에 들어간 시점이 아니어도 값을 채워줌 (Pk)
* 데이터를 가지고 있는 쪽이 비즈니스 로직을 가지고 있는게 좋다
@PostMapping("/members/new")
public String create(@Valid MemberForm form, BindingResult result){
if (result.hasErrors()) {
return "members/createMemberForm";
}
@NotEmpty ("이름은 필수로 입력해주세요.")
private String name;
@Vaild
NotEmpty가 붙어있는 변수에 값이 잘 들어갔는지 확인해준다.
@PostMapping("/members/new")
public String create(@Valid MemberForm form, BindingResult result){
if (result.hasErrors()) {
return "members/createMemberForm";
}
@Vaild 에서 오류가 있으면 튕겨버린다 원래.
하지만 BindingResult에 값이 들어왔으면 화면에 어떤 에러가 있는지 보여줄 수 있다.
==> front에서 에러를 받아서 화면을 처리할 수 있다.
* @Setter 제거하고 static으로 createBook을 만드는게 더 좋은 설계이다.
@PostMapping("/items/new")
public String create(BookForm form) {
Book book = new Book();
book.setStockQuantity(form.getStockQuantity());
book.setName(form.getName());
book.setPrice(form.getPrice());
book.setIsbn(form.getIsbn());
book.setAuthor(form.getAuthor());
itemService.saveItem(book);
return "redirect:/";
}
* 변경감지 = dirty checking
ex)
1. Book book = EntityManager.find(pk)를 통해 저장되어 있는 Entity를 반환
2. book.setName("어쩌고저쩌고")
--> JPA가 저장되어 있는 데이터의 값이 바뀐걸 보고 Transaction이 커밋되는 시점에 자동으로 수정해준다.
**** 준영속 엔티티 -> 영속성 컨텍스트가 더이상 관리하지 않는 엔티티****
준영속 엔티티는 JPA 영속성 컨텍스트가 관리하지 않기 때문에 값이 바뀌어도 자동으로 업데이트되지 않는다.
따라서
- 변경 감지 기능 사용
- 병합 (준영속 -> 영속) == EntityManager.Merge
@Transactional
public Item updateItem(Long itemId, Book param) {
Item findItem = itemService.findOne(itemId);
findItem.setPrice(param.getPrice());
findItem.setName(param.getName());
findItem.setPrice(param.getPrice());
return findItem;
}
위 코드 동작이 merge 메서드의 기능과 동일
Item item = em.merge(itemparam)
item != itemparam
파라미터로 넘어온 Item객체와 merge 반환값 Item객체는 다른 객체이다.
///주의점
merge는 선택 속성만 변경하는 것이 아니라 전부 다 변경이 된다.
즉, 모든 값이 들어있는 객체를 파라미터로 넘기지 않고 빈 값이 있으면 null로 업데이트 된다.
컨트롤러에서 엔티티 생성 X
트랜잭션이 있는 서비스 계층에 식별자(PK)와 변경할 데이터를 명확히 전달하자.
트랜잭션이 있는 서비스 계층에서 영속 상태의 엔티티를 조회하고, 데이터를 변경하자
'JPA' 카테고리의 다른 글
[JPA] JPQL - 페이징 (0) | 2023.05.08 |
---|---|
[JPA] JPQL- 기본 쿼리문 예시 (0) | 2023.05.08 |
[Spring Data JPA] 데이터 수정 / Dirty checking 시 save를 별도로 해줘야 한다 ? (0) | 2023.04.13 |
[SpringData JPA] 생성시간, 수정시간 자동 (JPA Auditing, BaseEntity) (0) | 2023.03.19 |
Spring JPA 기본 (0) | 2023.02.02 |