[Spring Boot] Spring Data JPA

SeoYoung Jung·2022년 4월 1일
0

spring boot jpa가 제공해주는 JpaRepository로 jpa 가 제공하는 공통 인터페이스를 사용가능하다.

  • 개발시에 대부분의 개발자들이 구현해야하는 여러 CRUD 기능을 인터페이스화 했다.

기존 Repository에는 모든 기능 구현
-> 이후 TEST

스프링 데이터 JPA기반 Repo에는

public interface MemberRepository extends JpaRepository<Member, Long> {
}

= 기능구현 끝!

JPA 의 주요 메서드

save(S) : 새로운 엔티티는 저장하고 이미 있는 엔티티는 병합한다.

delete(T) : 엔티티 하나를 삭제한다. 내부에서
EntityManager.remove() 호출

findById(ID) : 엔티티 하나를 조회한다. 내부에서 EntityManager.find() 호출

getOne(ID) : 엔티티를 프록시로 조회한다. 내부에서EntityManager.getReference() 호출

findAll(…) : 모든 엔티티를 조회한다. 정렬( Sort )이나 페이징( Pageable ) 조건을 파라미터로 제공할 수
있다

getOne() 메소드 추가 설명 넣기

쿼리 메소드의 기능

1.메소드 이름으로 쿼리를 생성한다.
2.메소드 이름으로 JPA namedquey 호출 (잘 사용 ㄴㄴ)
3 인터페이스에 쓰기

쿼리메소드 기능 정리하기

스프링 데이터 JPA가 제공하는 쿼리 메소드 기능
조회: find…By ,read…By ,query…By get…By,

findHelloBy 처럼 ...에 식별하기 위한 내용(설명)이 들어가도 된다.

-COUNT: count…By 반환타입 long
-EXISTS: exists…By 반환타입 boolean
-삭제: delete…By, remove…By 반환타입 long
-DISTINCT: findDistinct, findMemberDistinctBy
-LIMIT: findFirst3, findFirst, findTop, findTop3

@NamedQuery

ex]

@NamedQuery(
        name = "Member.findByUsername",
        query = "select m from Member m where m.username = :username"
)
public class Member {
	...
}

이를 JPA로 구현을 하게 된다면

public List<Member> findByUsername(String username) {
    return em.createNamedQuery("Member.findByUsername", Member.class)
    	.setParameter("username", username)
    	.getResultList();
}

나아가 스프링 데이터 JPA로 구현하면?

@Query(name = "Member.findByUsername")
List<Member> findByUsername(@Param("username") String username);

===========================================================

  • 스프링 데이터 JPA는 도메인 클래스 + .(점) + 메서드 이름
  • Named 쿼리가 없으면 앞서 알아본 메서드 이름으로 쿼리 생성 전략을 사용한다.
    NamedQuery를 잘 안쓰기는 하는데 유일한 장점이 있다.
    로딩 시점에 오류를 찾을수있음.

쿼리 = 정적 쿼리, 동적 쿼리 (동적 쿼리는 나중에)

***가장많이 쓰는 것

@Query("select m from Member m where m.username = :username and m.age = :age")
List<Member> findUser(@Param("username") String username, @Param("age") int age);

=================================================

=JPA와 스프링데이터 JPA의 차이는 뭘까?

= JPA란 자바 ORM(Object Relational Mapping) 기술에 대한 API 표준 명세

JPA는 특정 기능을 하는 라이브러리가 아니고, ORM을 사용하기 위한 인터페이스를 모아둔 것

JPA는 자바 어플리케이션에서 관계형 데이터베이스를 어떻게 사용해야 하는지를 정의하는 방법중 한 가지

JPA는 단순히 명세이기 때문에 구현이 없습니다.

JPA를 정의한 javax.persistence 패키지의 대부분은 interface , enum , Exception, 그리고 Annotation 들로 이루어져 있습니다.

JPA의 핵심이 되는 EntityManager 는 아래와 같이 javax.persistence 패키지 안에 interface 로 정의되어 있습니다.

스프링 데이터 JPA?

(사실 다른 것이 없었음 쉽게 사용하도록 도와주는 것일 뿐 좀 더 인터페이스화)

Spring Data JPA는 Spring에서 제공하는 모듈 중 하나로 JPA를 쉽고 편하게 사용할 수 있도록 도와줍니다.

기존에 JPA를 사용하려면 EntityManager를 주입받아 사용해야 하지만,

Spring Data JPA는 JPA를 한단계 더 추상화 시킨 Repository 인터페이스를 제공

Spring Data JPA가 JPA를 추상화 했다는 말은, Spring Data JPA의 Repository의 구현에서 JPA를 사용하고 있다는 것

@Query(값, DTO 조회)

=값, DTO를 조회하는 것도 똑같이 @Query("조건문")

*그런데 DTO조회는 JPQL new 명령어 사용 + 생성자가 맞는 DTO 필요하여 dto를 따로 생성해야 한다.

파라미터 바인딩

파라미터 바인딩 = 위치 기반, 이름 기반
*이름기반을 쓰자
왜? 위치가 변경 될 수 있기 때문이다.

스프링 데이터 JPA의 반환 타입

List<Member> findListByUsername(String username); //컬렉션
Member findMemberByUsername(String username); //단건
Optional<Member> findOptionalByUsername(String username); //단건 Optional

컬렉션 조회 => 이상한거 조회할때 null 이 아니라 빈컬렉션 반환한다.

단건조회=>값 없을 때 null

data 있을지 없을지 모르면 그냥 optional 쓰자

중복값 있으면 exception =-> 스프링 예외로 변환해야한다.

##페이징이란?

-페이징이랑 정렬기능 제공할게 - > 세부구현은 알아서해

-더보기해서 나머지 글 보는것 - slice로..

"page와slice 차이"

Page<Member> findByAge(int age, Pageable pageable);
  1. Page 반환 타입에 대해 페이징을 하는 메소드

  2. 메소드 이름으로 쿼리 생성 전략

  3. 페이징과 정렬을 위해 파라미터로 Pageable을 추가

=+) 정렬 조건이 복잡해지면 Sort.by로 하기엔 무리가 있다. 이 때는 @Query에 직접 작성

Page반환타입을 사용하면 = totalCount쿼리 자동으로 제공해서 따로 메서도 호출 안해도된다.

Page가 제공하는 다양한 메소드

getContent() : 조회한 페이지의 컨텐츠 목록

getTotalElements() : 순수 JPA에서 totalCount의 역할, 페이지 상관 없이 조회할 수 있는 element의 총 개수

-> 따로 totalCount를 위한 메서드를 호출하지 않아도 Page 반환 타입에서 이렇게 계산해준다.

getNumber() : 현재 페이지 번호

getTotalPages() : 조회할 수 있는 페이지 개수

isFirst() : 첫 번째 페이지인지 확인

hasNext() : 다음 페이지가 있는지 확인

Slice? (사실 Page인터페이스 상위임 +더보기)

Slice<Member> findByAge(int age, Pageable pageable);

Pageable에서 설정한 limit(두 번째 파라미터) 값보다 +1해서 조회하게 된다.

limit + 1해서 조회하는 이유는 다음으로 슬라이싱할("더보기") 엔티티가 아직 남아있나 확인하는 것이다.

-> 이 "+1" 부분이 바로 "더보기"의 기능을 수행하는 것이다.

+1은 단순 확인용이기 때문에, 스프링 데이터 JPA에서 마지막 결과는 날려버리고 Slice에 담게 된다.
=>list로도 페이징 가능한데 기능없이 그냥 조회만함

*불필요한 조인없애고 싶어 -> CountQuery설정하자 -> 성능 최적화

벌크성 수정 쿼리??

    
  public int bulkAgePlus(int age) {
    return em.createQuery("update Member m set m.age = m.age + 1 where m.age >= :age")
        .setParameter("age", age)
        .executeUpdate();
}
   
    
    
    = executeUpdate()있어야 DB에 쿼리가 반영
  
  <spring data jpa>
    
    ```java
@Modifying
@Query("update Member m set m.age = m.age + 1 where m.age >= :age")
int bulkAgePlus(@Param("age") int age);
    ```
    
    =spring datga jpa는 @ModifyingexecuteUpdate() 역할 
    
  ****주의****
    벌크연산도 DB에 연산함 ->영속성 컨텍스트의 엔티티와 DB 데이터 간에 차이 -> 영속성 컨텍스트 초기화 하자!!!!!!!!!!!! 
 
     clearAutomatically = true 옵션을 수행하면 벌크 연산 수행 후 자동으로 영속성 컨텍스트를 비워준다.





'





profile
뚱땅뚱땅개발자

0개의 댓글