Spring/JPA

    영속성 전이(Cascade) ManyToOne 시 주의할점 - 상위 엔티티 삭제 문제

    @ManyToOne(cascade=CascadeType.ALL) 또는 @ManyToOne(cascade=CascadeType.REMOVE) 일 때, Many쪽 (자식 엔티티)를 제거할 때 주의 하여야 한다. 연관된 부모도 삭제하기 때문이다. 연관된 부모를 삭제하게 된다면 그 부모를 참조하고 있던 자식 엔티티들이 고아객체가 되어버린다. 상황 Member(회원)과 Order(주문) 테이블의 관계가 1:N 이라고 할 때, Member와 Order는 1:N 단방향 관계로 Order는 @ManyToOne- Member 필드를 참조한다. 이 때, Order가 @ManyToOne(cascade=CascadeType.ALL) 또는 @ManyToOne(cascade=CascadeType.REMOVE) 일 때 Order를..

    Spring Data Jpa Cursor based Pagenation (커서 기반 페이지네이션) 예제 (JpaRepository 커서 기반 페이지네이션

    환경 Spring boot 2.7.6 hibernate 5.6.4 QueryDsl를 사용하면 더 편리하겠지만, Spring Data Jpa Repository Interface만을 이용하여 조회하는 예제이다. Repository는 Interface이고, Interface에 페이징을 계산하는 비즈니스 연산을 넣는것은 옳지 않다고 생각되어 Service Class에서 연산하여 Repository에 위임한다. Post라는 게시글의 cursor를 postId로 가정하고, postId와 createdAt의 역순으로 조회하는 커서 기반 페이지네이션 예이다. 이 때, 다음 게시물이 있는지 없는지 여부를 표현하기 위해 응답객체에 hasNext를 추가했다. Post Class @Entity @Table(name = "p..

    JPA Entity의 Field Data Type은 primitive, Wrapper 중 어떤것을 사용해야 할까?

    Jpa Entity Data Type Entity의 filed Data Type을 Primitve로 지정해야 할까 Wrapper Type으로 지정해야 할까? 결론 1. PK에는 Long(Wrapper Class) 을 사용하자 Wrapper Class 를 사용함으로써 Null을 대입해놓을 수 있는데, 명시적으로 PK가 아직 할당되지 않았음을 의미할수 있다. 반면 primivite type은 null 을 표시할 방법이 없다 JPA에서 Wrapper 클래스가 Number의 하위 타입인 경우(int, long 등)에는 해당 값이 0인 경우에만 이를 새로운 엔티티라 판단한다. 0이 아니라면, save 시 merge가 동작하여 select + insert 쿼리 2번을 실행하게 된다. 2. Null이 필요한 컬럼인지..

    @NotNull vs @Column(nullable = false), JPA에서 INSERT 전에 Null 검사하는 방법

    @Column(nullable=false) 옵션은 기본적으로는 INSERT 시 null값 삽입을 막아주지 못한다. 결론부터, @Column(nullable = false) 만 필드에 사용하면, INSERT시에 Null 검사 를 하지 않는다 이것은 기본 정책이며 바꿀 수 있다. @Column(nullable = false) 만 사용해서 null값 방지를 하려면 spring.jpa.properties.hibernate.check_nullability=true 옵션 사용. 아래를 참고하자. Null검사를 하고 싶다면 @NotNull 어노테이션을 사용하여 @Column(nullable = false) 와 함께 정의하면, INSERT 전에 방지한다. JPA @Column(nullable = false) JPA 에..

    JpaRepository에서 save시 select 쿼리가 먼저 실행되는 이유

    Spring Data Jpa - JpaRepository에서 save시 select 쿼리가 먼저 실행되는 이유 Entity의 id가 GeneratedValue가 sequence(또는 identity)가 아니고, 직접 id를 set 할 때, 하이버네이트에서 엔티티 Id 생성 전략이, 개발자가 직접 Id를 만들 고 엔티티 객체 저장 시 select 쿼리가 나간다. 결론부터 JpaRepository.save(entity) 를 이용해서 엔티티 객체를 저장할 때, entityManager.persist or entityManager.merge 를 호출한다. 이 때, JpaRepository의 구현체인 SimpleJpaRepository는 isNew 메서드를 통해 id값이 없으면 새 엔티티라고 판단하고, em.pe..