본문 바로가기
Web/Spring

[Spring] Spring Data JPA (2)

by 희조당 2022. 8. 13.
728x90

📌 기본 설정

Spring Boot 프로젝트를 생성할 때 'Auto Configuration'이라는 기능 덕분에 관련된 설정이 자동으로 추가된다.

Spring Data JPA도 마찬가지이지만 구체적인 값을 지정해야 데이터베이스를 사용할 수 있다.

  • DB를 위한 JDBC 드라이버 설정하기
  • Spring Boot 프로젝트 내 DB 설정하기

✔️ Application.properties 설정 (프로젝트 내 DB 설정)

spring.datasource.driver-class-name=com.mysql.jdbc.Driver
spring.datasource.url=jdbc:mysql://localhost:3306/{DB명}
spring.datasource.username=
spring.datasource.password=

✔️ Spring Data JPA를 위한 스프링 부트 설정

// application.properties
spring.jpa.hibernate.ddl-auto= // 자동으로 DDL을 생성할 지 (스키마 생성)
spring.jpa.generate-ddl=false // DDL 생성 시 데이터베이스의 고유기능을 사용할지
spring.jpa.show-sql=true // 실행되는 SQL문을 보여줄지
spring.jpa.database=mysql // 어떤 데이터베이스를 사용하는지

✍️ 스키마 생성 옵션 ✍️

  • create : 기존 테이블 삭제 후 재 생성
  • create-drop : create와 같으나 종료 시점에 테이블을 drop
  • update : 변경된 부분만 반영
  • validate : 엔티티와 테이블이 정상적으로 매핑되었는지 확인
  • none : 사용하지 않음

📌 Spring Data JPA에서

개발에 필요한 것은 단지 두 종류의 코드만으로 가능하다.

  • JPA를 통해 관리하게 되는 객체를 위한 엔티티(Entitiy) 클래스
  • 엔티티 객체들을 처리하는 기능을 가진 Repository

Repository는 Spring Data JPA에서 제공하는 인터페이스로 설계한다.

자동으로 객체를 생성하고 실행하는 구조라 개발자는 단순히 인터페이스를 하나 정의하면 된다.


📌 엔티티 클래스

✔️ @Entitiy

  • 엔티티 클래스는 무조건 이 annotation을 붙여야 한다.
  • 클래스와 클래스의 인스턴스들이 JPA로 관리되는 엔티티라는 것을 의미.
  • 옵션에 따라 자동으로 테이블 생성 가능하고 멤버 변수에 따라서 자동으로 칼럼들도 생성된다.

✔️ @Table

  • @Entity와 같이 사용할 수 있는 annotation.
  • 단순히 테이블 이름뿐만 아니라 인덱스 등을 생성하는 설정도 가능하다.

이런 식으로!

✔️ @Id

  • @Entity가 붙은 클래스는 Primary Key를 꼭 지정해야 한다.
  • 입력한 값을 사용하는 것이 아니라면 @GeneratedValue라는 annotation을 같이 사용한다.

✔️ @GeneratedValue

  • @GeneratedValue(strategy = GenerationType.{키 생성 전략}은 키 생성 전략에 따라 PK를 자동으로 생성합니다.

키 생성 전략


📌 JpaRepository 인터페이스

Spring Data JPA가 제공하는 API 중 가장 많이 사용하는 것이 JpaRepository이다.

CRUD , 페이징, 정렬과 같은 작업들을 메서드 호출 형태로 처리한다.

엔티티의 타입과, @Id의 타입을 넘겨준다.

JpaRepositoy 상속구조

public interface ExampleRepository extends JpaRepository<T, ID> {
	
    // Insert or Update
    <S extends T>S.save(Entity);
    
    // Select
    Optional<T> findById(ID); // 데이터베이스를 먼저 이용
    Optional<T> getOne(ID); // 지연 처리, @Transactional 필요
    
    // Delete
    Repository.deleteById(ID);
    void delete(Entitiy);
	
    //.. 그 외
}

📌 페이징/정렬 처리

Spring Data JPA는 페이징 처리와 정렬에 PagingAndSortRepository의 메서드 findAll()을 사용한다.

 

✔️ Pageable 인터페이스

  • 페이지 처리에 필요한 정보를 전달하는 인터페이스.
  • 실제 객체를 생성할 때는 org.springframework.data.domain.PageRequest 클래스를 사용한다.
  • protected로 선언되어 new()를 사용할 수 없고, static 메소드인 of()를 이용해서 처리한다.

✔️ of()의 형태 

  • of (int page, int size) : 페이지 번호와 개수
  • of (int page, int size, Sort.Direction direction, String ···props) : 페이지 번호와 개수, 정렬 방향과 기준 필드들
  • of (int page, int size, Sort sort) : 페이지 번호와 개수, 정렬 관련 정보
// Example
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.PageRequest;

@Test
public void testPageDefault() {
   // 페이징 처리는 0부터 시작한다!!	
   Pageable pageable = PageRequest.of(0, 10); // 1페이지, 10개
   Page<T> test = testRepository.findAll(pagealbe);
}

✔️ 정렬하기

  • org.springframework.data.domain.Sort를 추가해서 사용한다.
  • 한 개 이상의 필드로 정렬할 수 있다.
// Example
Sort sort = Sort.by("field").descending(); // 내림차순   

Pageable pageable = PageRequest.of(0, 10, sort);   

Page<T> test = testRepository.findAll(pagealbe);
  • and()를 사용해서 여러 개의 정렬 조건을 다르게 할 수 있다.
// Example
Sort sort1 = Sort.by("field1").descending();
Sort sort2 = Sort.by("field2").ascending();
Sort sort3 = sort1.and(sort2); // and를 이용한 연결

Pageable pageable = PageRequest.of(0, 10, sort3);

📌 @Query 어노테이션

쿼리 메서드들은 편리하지만 어떤 상황에선 사용하기 불편한 경우가 생긴다. (복잡한 조건, 조인 등)

일반적인 경우 간단한 처리만 쿼리 메서드를 쓰고 이 annotation을 사용한다.

 

💡 특징

  • 필요한 데이터만 선별적으로 추출할 수 있다.
  • 데이터베이스에 맞는 순수한 SQL (Native SQL)을 사용할 수 있다. (nativeQuery = true)
  • insert, update, delete와 같은 select가 아닌 DML 등을 처리할 수 있다.

💡 파라미터 바인딩하는 방법

  • '?1, ?2'와 1부터 시작하는 파라미터 순서를 이용하는 방식
  • ':xxx'와 같이 ':파라미터 이름'을 활용하는 방식
  • '#{ }'과 같이 자바 빈 스타일을 이용하는 방식

가독성을 위해서 꼭 이름 기반으로 바인딩을 해야한다! 

그리고 파라미터에는 @Param(" ") annotation으로 메서드에 들어오는 파라미터의 이름을 지정해준다.

// Example
public interface UserRepository extends JpaRepository<User, Long> {
    @Query("select u from User u where u.username = :name")
    List<User> methodName(@Param("name") String username);
}

✔️ Object[] 리턴

  • 큰 장점 중 하나로 쿼리 메서드는 엔티티 타입의 데이터만 추출하지만, @Query는 필요한 데이터만을 Object[] 형태로 선별적으로 추출할 수 있다.
// Example
public interface MemoRepository extends JpaRepository<User, Long> {
    @Query(value = "select m.mno, m.memoText, CURRENT_DATE from Memo m where m.mno > :mno",
    countQuery = "select count(m) from Memo m where m.mno > :mno")
    Page<Object[]> getListWithQueryObject(Long mno, Pageable pageable);
}

 

댓글