JPA 객체지향 쿼리 언어(JPQL) - 벌크 연산

2022. 7. 23. 23:34·공부/JPA
반응형

출처 : 자바 ORM 표준 JPA 프로그래밍 인프런 강의

 

JPA 게시글은 대부분 인프런의 김영한님의 강의인 '자바 ORM 표준 JPA 프로그래밍' 기반으로 내용을 정리했습니다.

 

벌크 연산

  • 벌크 연산 : 일반적으로 잘 알고있는 SQL의 UPDTAE, DELETE
  • 재고가 10개 미만인 모든 상품의 가격을 10% 상승하려면?
  • JPA 변경 감지 기능으로 실행하려면 너무 많은 SQL 실행
    • 재고가 10개 미만인 상품을  리스트로 조회
    • 상품 엔티티의 가격을 10% 증가
    • 트랜잭션 커밋 시점에 변경감지 동작
  • 변경된 데이터가 100건이라면 100번의 UPDATE SQL이 실행

 

예제

  • 쿼리 한 번으로 여러 테이블 로우를 변경(엔티티)
  •  executeUpdate()의 결과는 영향받은 엔티티 수 반환
  • UPDATE, DELETE 지원
  • INSERT(insert into ...select, 하이버네이트 지원)
  • 모든 회원의 나이를 20살로 변경
int resultCount = em.createQuery("update Member m set m.age = 20")
        .executeUpdate();

System.out.println("resultCount = " + resultCount);
Hibernate: 
    /* update
        Member m 
    set
        m.age = 20 */ update
            Member 
        set
            age=20
resultCount = 3

 

 

벌크 연산 주의점

  • 벌크 연산은 영속성 컨텍스트를 무시하고 데이터베이스에 직접 쿼리 한다.
  • 해결방법(둘 중에 하나 선택) 
    • 벌크 연산을 먼저 실행하거나
    • 벌크 연산 수행 후 영속성 컨텍스트 초기화
Team teamA = new Team();
teamA.setName("팀A");
em.persist(teamA);

Team teamB = new Team();
teamB.setName("팀B");
em.persist(teamB);

Member member = new Member();
member.setUsername("회원1");
member.setTeam(teamA);
em.persist(member);

Member member2 = new Member();
member2.setUsername("회원2");
member2.setTeam(teamA);
em.persist(member2);

Member member3 = new Member();
member3.setUsername("회원3");
member3.setTeam(teamB);
em.persist(member3);

//  em.flush();
//  em.clear();

int resultCount = em.createQuery("update Member m set m.age = 20")
        .executeUpdate();

System.out.println("resultCount = " + resultCount);
System.out.println("member.getAge() = " + member.getAge());
System.out.println("member2.getAge() = " + member2.getAge());
System.out.println("member3.getAge() = " + member3.getAge());

쿼리문 위에 영속성 컨텍스트를 초기화시키는 코드를 주석처리한다. 물론 flush야 쿼리가 실행되면 자동적으로 flush가 되긴하는데 문제는 clear이다. clear가 없는 경우 영속성 컨텍스트에는 나이가 20살로 변경되지 않고, 그대로 초기값인 0이 남아있다.

resultCount = 3
member.getAge() = 0
member2.getAge() = 0
member3.getAge() = 0

그러니 영속성 컨텍스트를 초기화해서 값을 불러올 필요가 있다.

int resultCount = em.createQuery("update Member m set m.age = 20")
        .executeUpdate();
em.clear();
Member findMember = em.find(Member.class, member.getId());
System.out.println("findMember = " + findMember.getAge());

이런 식으로 벌크 연산 후 영속성 컨텍스트를 초기화시켜야 한다.

반응형
저작자표시 비영리 변경금지 (새창열림)
'공부/JPA' 카테고리의 다른 글
  • Spring Data JPA - 예제 도메인 모델과 동작확인
  • Spring Data JPA - 프로젝트 환경 설정
  • JPA 객체지향 쿼리 언어(JPQL) - Named 쿼리
  • JPA 객체지향 쿼리 언어(JPQL) - 엔티티 직접 사용
데부한
데부한
어차피 할 거면 긍정적으로 하고 싶은 개발자
    반응형
  • 데부한
    동동이개발바닥
    데부한
  • 전체
    오늘
    어제
    • 분류 전체보기 (307)
      • 방통대 컴퓨터과학과 (27)
        • 잡담 (9)
        • 3학년1학기 (17)
      • 프로젝트 및 컨퍼런스 회고 (1)
        • 프로젝트 (4)
        • 한이음 프로젝트 (0)
        • 회고 (3)
      • 공부 (165)
        • Spring (37)
        • JPA (71)
        • 인프런 워밍업 클럽_BE (10)
        • Java (6)
        • React.js (27)
        • 넥사크로 (11)
        • 기타 (3)
      • 알고리즘 (85)
        • 알고리즘 유형 (10)
        • 알고리즘 풀이 (57)
        • SQL 풀이 (18)
      • 에러 해결 (13)
      • 잡담 (7)
        • 국비교육 (2)
        • 구매후기 (5)
        • 진짜 잡담 (0)
  • 블로그 메뉴

    • Github
    • Linkedin
    • 홈
    • 방명록
    • 글쓰기
    • 관리
  • 링크

  • 공지사항

  • 인기 글

  • 태그

    IT
    프로그래머스
    자바스크립트
    운영체제
    프론트엔드
    넥사크로
    RESTful
    SpringBoot를 이용한 RESTful Web Service 개발
    react
    Java
    oracle
    egov
    MSA
    알고리즘
    에러해결
    springboot
    Spring
    토비의스프링부트
    SQL
    방통대
    JPA
    개발자
    인프런
    전자정부프레임워크
    QueryDSL
    기출문제
    스프링부트
    백준
    코딩테스트
    토이프로젝트
  • 최근 댓글

  • 최근 글

  • hELLO· Designed By정상우.v4.10.3
데부한
JPA 객체지향 쿼리 언어(JPQL) - 벌크 연산
상단으로

티스토리툴바