JPA
-
JPA HintJPA/스프링 데이터 JPA 2023. 8. 12. 00:19
JPA 쿼리 힌트 (SQL 힌트가 아니라 JPA 구현체에게 제공하는 힌트) JPA에서 데이터를 변경할 때 변경 감지라는 기능을 사용해서 트랜잭션 안에서 데이터를 변경한다. 이 때 스냅샷을 생성하기도 하고 변경을 위해서 메모리를 소비한다. 그런데 진짜 조회만 할 때에는 이런 것들이 필요없으니 최적화를 해줘야한다. public interface MemberRepository extends JpaRepository { @QueryHints(value = @QueryHint(name = "org.hibernate.readOnly", value = "true")) Member findReadByUsername(String username); // 조회만 할 때 조회만 해서 쿼리를 최적화 해주는 작업 } @Quer..
-
@EntityGraph - 어노테이션으로 fetch joinJPA/스프링 데이터 JPA 2023. 8. 12. 00:04
JPA 사용 시 N + 1 문제를 해결해주는 기능이다. N + 1 문제를 해결하기 위해 fetch join이 중요하다는 것은 여러번 강조했었다. @EntityGraph는 쉽게 말해 fetch join을 쉽게 해주는 기능이다. 스프링 데이터 JPA는 쿼리를 최소한으로 작성하는데 fetch join을 하기 위해서는 무조건 JPQL을 작성해야하기 때문에 메서드 이름과 어노테이션으로 fetch join 최적화를 하기 위한 기능이 @EntityGraph이다. public interface MemberRepository extends JpaRepository { @Override // findAll()은 상속받은 상위 인터페이스에 있으므로 오버라이드 @EntityGraph(attributePaths = {"team..
-
벌크성 수정 쿼리JPA/스프링 데이터 JPA 2023. 8. 11. 23:21
데이터 하나를 수정할 때에는 변경 감지가 좋지만 모든 데이터를 수정할 때, 예를 들어 모든 상품의 가격을 10% 인상을 할 때에는 벌크 연산이 좋다. @Modifying // JPA에서 query.executeUpdate()과 같은 기능 @Query("update Member m set m.age = m.age + 1 where m.age >= :age") int bulkAgePlus(@Param("age") int age); 스프링 데이터 JPA에서는 @Modifying을 넣어준 다음 update 쿼리를 날려주면 된다. 반환은 update 되는 데이터의 개수이므로 int로 반환해주면 된다. @Modifying을 넣어주지 않으면 에러가 난다. @Test public void bulkUpdate() thr..
-
스프링 데이터 JPA의 페이징과 정렬JPA/스프링 데이터 JPA 2023. 8. 11. 23:00
페이징과 정렬 파라미터 'org.springframework.data.domain.Sort' : 정렬 기능 'org.springframework.data.domain.Pageable' : 페이징 기능 (내부에 'Sort' 포함) data.jpa가 아니라 data.domain이다. 즉, 어떤 SQL 언어를 사용하든 간에 정렬 방법은 같다는 것이다. 특별한 반환 타입 'org.springframework.data.domain.Page' : 추가 count 쿼리 결과를 포함하는 페이징 (totalCount 포함) 'org.springframework.data.domain.Slice' : 추가 count 쿼리 없이 다음 페이지만 확인 가능 'List' : 추가 count 쿼리 없이 결과만 반환 Page publ..
-
@Query - 쿼리 정의하기JPA/스프링 데이터 JPA 2023. 8. 11. 21:20
public interface MemberRepository extends JpaRepository { @Query("select m from Member m where m.username = :username and m.age = :age") List findUser(@Param("username") String username, @Param("age") int age); } Repository에 @Query 어노테이션으로 쿼리를 정의해서 사용할 수 있다. 이러한 방식의 장점은 첫 번째로 findByUsernameAndAgeGreaterThan() 같이 메서드 이름으로 자동으로 쿼리를 날려주는 방식은 2가지 조건만으로도 메서드명이 길어지는데 위의 방식은 그렇지 않고, 내가 보내고싶은 쿼리를 명확하게 알..
-
쿼리 메서드 - 메서드 이름으로 자동 쿼리 생성JPA/스프링 데이터 JPA 2023. 8. 11. 20:50
메서드 이름으로 쿼리 지정 스프링 데이터 JPA는 메서드 이름으로 쿼리를 자동으로 입력해준다. public List findByUsernameAndAgeGreaterThan(String username, int age) { return em.createQuery("select m from Member m where m.username = :username and m.age > :age") .setParameter("username", username) .setParameter("age", age) .getResultList(); } 스프링 데이터 JPA를 사용하지 않고 그냥 JPQL을 이용해서 쿼리를 작성했을 때이다. 스프링 데이터 JPA를 사용하면 메서드 이름만으로 쿼리를 자동으로 작성해준다. publ..
-
스프링 데이터 JPA의 간단한 소개JPA/스프링 데이터 JPA 2023. 8. 11. 15:53
스프링 데이터 JPA란 중복되는 JPA 코드들을 인터페이스로 묶어둔 다음 스프링 데이터 JPA가 실행 시점에서 구현체를 만들어줘서 간편하게 데이터들을 관리할 수 있는 기술이다. @Repository public class MemberJpaRepository { @PersistenceContext private EntityManager em; public Member save(Member member) { em.persist(member); return member; } public Member find(Long id){ return em.find(Member.class, id); } } 위의 코드는 기존의 repository 코드이다. save, find같은 기능들은 모든 테이블에서 공통적으로 사용하는 ..
-
OSIV와 성능 최적화JPA/JPA 활용 2023. 8. 11. 14:02
OSIV (Open Session In View) 스프링부트에서 트랜잭션을 시작할 때 데이터베이스 커넥션을 가지고온다. -> 데이터베이스 커넥션 : 한 번에 접근할 수 있는 쓰레드 풀 같은 커넥션 이 때 OSIV가 켜져있으면 트랜잭션이 끝나고 컨트롤러 계층까지 가도 데이터베이스 커넥션을 반환하지 않는다. 그 이유는 Lazy 로딩을 생각하면 데이터가 필요한 시점에 프록시 객체를 db에서 가져오기 때문이다. 영속성 컨텍스트가 데이터베이스를 계속 붙잡고 있어야 한다. api가 유저한테 반환이 되고 response가 나갈 때 까지 데이터베이스 커넥션을 붙잡고 있는 것이다. OSIV는 기본이 true, 켜져있는 상태이다. OSIV 장점 지연 로딩은 영속성 컨텍스트가 살아있어야 하고, 영속성 컨텍스트는 기본적으로 ..