본문 바로가기

PROGRAMMING/JPA

(16)
[JPA] Bulk 삭제 후 이전 변경사항 반영 안되는 경우 문제 상황(Spring Data JPA) 작업 할 내용의 순서가 1. 노트를 삭제한다.(정확하게는 삭제 flag를 true로 반영) 2. 노트에 태그된 태그들을 삭제한다 이렇게였는데 2번을 진행 한 후 확인해보면 1번 내용이 반영되지 않는 문제 발생 원인 벌크성 수정/삭제 쿼리의 경우 영속성 컨텍스트를 무시하기 때문에 벌크성 쿼리 실행전에 db와 싱크를 맞추는 작업을 해야된다. 해결방법 EntityManager의 flush와 clear를 실행해야 하는데 @Modifying(clearAutomatically = true, flushAutomatically = true) @Query("delete from NoteTag NT where NT.note.id = :noteId") void bulkDelete(@..
[JPA] Blob 컬럼 타입 사용 시 주의할 점 DB : MariaDB Framework : Spring boot 2.x No serializer found for class java.io.ByteArrayInputStream BLOB 위와 같은 에러 발생 직렬화 할수 없다 뭐 이런얘기 같은데 검색해보니 byte로 변환하고 어쩌고 하는 방법이 많이 나왔는데 간단하게 컬럼 타입이랑 엔티티에서 자료형을 따로 주면 된다. 기존 @Column(name = "note_contents") private Blob contents; 변경 @Column(name = "note_contents", columnDefinition = "BLOB") private byte[] contents; 아주 잘 출력되는것을 확인할 수 있다. 추가로 CLOB으로 매핑하려면 byte대신..
[QueryDSL] QueryDSL 프로젝트에 세팅하기 1. 아래 스크립트 build.gradle에 추가 queryDslVersion = "5.0.0" 이 부분을 꼭 명시해줘야 한다. 2. 테스트 테스트 엔티티를 생성하고 Gradle탭에서 (안 보인다면 intelliJ기준 하단 좌측에 네모 박스 눌러보기) {project name} > Task > other > compileQuerydsl 더블클릭 or 빌드 후 build.gralde에서 설정한 위치로 가보면 위 스크립트 기준 "$buildDir/generated/querydsl" Q파일이 생성된것을 확인할 수 있다.
[DataJPA] 페이징 사이즈 옵션 주기 1. 글로벌하게 적용하기 설정을 application.yml 파일로 한 경우 spring: data: web: pageable: default-page-size: 10 max-page-size: 2000 이와같이 설정하면 한페이지에 10개씩(default는 20), max는 2000개로 설정할 수 있다. 2. 부분 적용하기 @GetMapping("/members") public Page list(@PageableDefault(size = 5) Pageable pageable){ Page page = memberRepository.findAll(pageable); return page.map(MemberDto::new); } @PageableDefault 어노테이션을 사용해서 size를 설정하면 globa..
[JPA] 변경 감지와 병합 웹에서 변경 데이터를 반환받아 변경해야 할 때 보통 객체를 생성해서 값을 세팅하는데 새로 생성한 객체는 id가 세팅되기 때문에 식별자는 존재하지만 영속성 컨텍스트에서는 관리하지않는 준영속 객체다. 이 객체는 JPA가 관리하지 않기 때문에 더티체킹(변경감지)가 일어나지 않는데 이러한 객체를 DB에 반영하는 방법으로 1. 병합(머지) 2. 변경 감지 두가지 있다. 예를 들어 Book 데이터를 변경할 때 병합 동작방식 1. merge()를 실행한다. 2. 파라미터로 넘어온 엔티티의 식별자 값(ID)으로 1차 캐시에서 조회한다. -> 1차 캐시에 없다면 DB에서 조회하고 1차 캐시에 저장한다. 3. 이렇게 조회한 Book 엔티티는 영속상태로 이 엔티티에 파라미터로 넘어온 값들을 다시 세팅한다. (1차 캐시 포함..
[JPQL] 묵시적&명시적 조인 JPQL은 SQL과 달리 객체를 대상으로 쿼리를 작성하는 것으로, 조인 관계에 있는 엔티티를 select절에서 가져올 수 있다. 하지만 위와 같이 사용하면 실제 작성한 것과 다른 쿼리가 달라가 묵시적 조인이 발생하게 되는데 이를 조심해야 한다. 예를 들어 위와 같은 Member 엔티티 안에 Team이 다대일 연관관계로 있으면 select m.team from Member m 위와 같이 from의 Member에서 team을 가져올 수가 있다. 하지만 실제로 실행되는 쿼리를 보면, 내가 실제 실행한 쿼리와는 다르게 team과 inner join이 발생하는 것을 확인할 수 있다. 이러한 묵시적 조인의 단점은 눈에 보이지 않는 조인이 실제 쿼리가 날라갈 때 발생함으로써 나중에 쿼리를 추적할때 시간이 걸리고 튜닝..
[JPQL] Enum 타입 파라미터 바인딩 대부분 타입이 일반적으로 쿼리에 where절 필터 걸듯이 걸면 되는 반면 Enum타입은 패키지 명까지 모두 선언해줘야 한다는 특이사항이 있다. 위 예제에서 type은 Enum class인데 패키지 위치가 jpql > MemberType 이기 때문에 jpql.MemberType.ADMIN으로 입력해야 한다. 파라미터 바인딩할 때에도 'ADMIN' 단순 String이 아닌 MemberType.ADMIN으로 바인딩해줘야 한다.
[JPQL] 페이징 처리 mysql과 oracle로 페이징 처리를 하면서 느꼇던 불편함을 JPQL을 사용하면 간단하게 처리가 가능하다. 회원 테이블에서 나이 오름차순으로 50번째부터 100명을 가져오는 경우 우선 oracle을 예로 들면 1. 회원테이블을 나이 asc로 정렬 2. 정렬한 데이터에서 150명을 필터링 3. 필터링 된 데이터에서 50번째 미만은 다시 필터링 이렇게 일련의 과정을 거치는 데 쿼리가 3중으로 구성된다. 하지만 JPQL로 개발하면 이렇게 간단하게 가능하다. 실제 실행되는 쿼리는 설정되어있는 db에 맞춰 변환되며 오라클의 경우 이렇게 변환되어 실행된다.