📌 기본 설정
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의 타입을 넘겨준다.
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);
}
'Web > Spring' 카테고리의 다른 글
[Spring] Spring의 DB 접근 기술 (0) | 2022.08.23 |
---|---|
[Spring] Spring의 핵심 : IoC, DI (23.05.16 updated) (0) | 2022.08.23 |
[Spring] Spring vs Spring Boot (2) (0) | 2022.08.23 |
[Spring] Spring vs Spring Boot (1) (0) | 2022.08.19 |
[Spring] Spring Data JPA란? (0) | 2022.08.13 |
댓글