다음을 참조하여 작성하였습니다. 감사합니다.🙇🏻♂️
[Configure Hibernate Naming Strategy(Spring-docs)](https://docs.spring.io/spring-boot/docs/2.1.3.RELEASE/reference/htmlsingle/#howto- configure-hibernate-naming-strategy )
[Naming Strategy (hibernate-docs)](http://docs.jboss.org/hibernate/orm/5.4/userguide/html_single/ Hibernate_User_Guide.html#naming)
즉시로딩(EAGER)는 예측이 어렵고 어떤 SQL이 실행될지 추적하기 어려움
JPQL의 경우 FetchType과는 별개로 입력한 SQL이 그대로 실행되므로 EAGER일 경우 한 번 SQL이 실행되는 N + 1 문제 발생
실무에서는 모든 연관관계를 지연로딩(LAZY)로 설정
연관된 엔티티를 함께 조회해야 할 경우 fetch join 또는 엔티티 그래프 기능 사용
fetch join : 조회한 엔티티를 객체 그래프 접근 방식으로 접근하는 방법
엔티티 그래프 : 원하는 그룹만 조회하는 방법
@XToOne은 기본이 즉시 로딩이므로 fetch = FetchType.LAZY로 직접 지연로딩으로 설정
컬렉션은 필드에서 초기화
필드에서 바로 초기화 하는 것이 null 문제에서 안전
Member member = new Member();
System.out.println(member.getOrders().getClass());
em.persist(team);
System.out.println(member.getOrders().getClass());
//출력 결과
class java.util.ArrayList
class org.hibernate.collection.internal.PersistentBag
- 하이버네이트는 엔티티를 영속화 할 때, 컬렉션을 하이버네이트가 제공하는 내장 컬렉션으로 변경
- 엔티티의 기존 컬렉션을 삭제할 경우 하이버네이트 내장 컬렉션이 아니게 되어 문제가 발생
카멜 케이스 -> 언더스코어(memberPoint -> memberpoint)
.(점) -> (언더스코어)
대문자 -> 소문자
논리명 생성, 물리명 적용
spring.jpa.hibernate.naming.physical-strategy
: 모든 논리명에 적용되며 실제 테이블에 적용// application.properties
spring.jpa.hibernate.naming.implicit-strategy:
org.springframework.boot.orm.jpa.hibernate.SpringImplicitNamingStrategy
spring.jpa.hibernate.naming.physical-strategy:
org.springframework.boot.orm.jpa.hibernate.SpringPhysicalNamingStrategy
Cascade
특정 엔티티의 영속성 상태가 변경되었을 때,
이를 연관된 엔티티에도 전파시킬지 선택하는 옵션.
연관관계 편의 메소드
양방향 관계의 경우 양쪽 엔티티에 모두 값을 입력해야 객체 그래프 탐색 가능,
편하게 값을 입력하기 위한 메소드
예제
@Entity
@Table(name = "orders")
@Getter
@Setter
public class Order {
@Id
@GeneratedValue
@Column(name = "order_id")
private Long id;
@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "member_id")
private Member member;
@OneToMany(mappedBy = "order", cascade = CascadeType.ALL)
private List<OrderItem> orderItems = new ArrayList<>();
@OneToOne(fetch = FetchType.LAZY, cascade = CascadeType.ALL)
@JoinColumn(name = "delivery_id")
private Delivery delivery;
private LocalDateTime orderDate; // 주문시간
@Enumerated(EnumType.STRING)
private OrderStatus status; // 주문상태[ORDER, CANCEL]
// == 연관관계 메소드 == //
public void setMember(Member member) {
this.member = member;
member.getOrders().add(this);
}
public void addOrderItem(OrderItem orderItem) {
orderItems.add(orderItem);
orderItem.setOrder(this);
}
public void setDelivery(Delivery delivery) {
this.delivery = delivery;
delivery.setOrder(this);
}
}
@Entity
@Getter
@Setter
public class Category {
@Id
@GeneratedValue
@Column(name = "category_id")
private Long id;
private String name;
@ManyToMany
@JoinTable(
name = "category_item",
joinColumns = @JoinColumn(name = "category_id"),
inverseJoinColumns = @JoinColumn(name = "item_id")
)
private List<Item> items = new ArrayList<>();
@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "parent_id")
private Category parent;
@OneToMany(mappedBy = "parent")
private List<Category> child = new ArrayList<>();
// == 연관관계 메소드 == //
public void addChildCategory(Category child) {
this.child.add(child);
child.setParent(this);
}
}