MySQL과 연동하고 실습을 통해 JPA를 알아봅니다.
학습 로드맵
선행 조건
참고
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<scope>runtime</scope>
</dependency>
spring:
datasource:
driver-class-name: com.mysql.jdbc.Driver
url: jdbc:mysql://디비주소
username: 아이디
password: 비밀번호
jpa:
hibernate:
ddl-auto: update
generate-ddl: true
show-sql: true
database: mysql
database-platform: org.hibernate.dialect.MySQL5InnoDBDialect
logging:
level:
org:
hibernate: info
import lombok.*;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
@Entity
@Getter
@Setter
@NoArgsConstructor
@ToString
public class Board {
@Id
@GeneratedValue
Long id;
private String username;
private String content;
@Builder
public Board(String username, String content) {
this.username = username;
this.content = content;
}
}
엔티티와 관련된 포스팅은 아래 두개 링크 걸어 뒀습니다!
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.Query;
import java.util.List;
public interface BoardRepository extends JpaRepository<Board, Long> {
List<Board> findBoardByContent(String content);
// id > ? ORDER BY id DESC limit ?, ?
List<Board> findByIdGreaterThanOrderByIdDesc(Long id, Pageable paging);
// id > ? limit ?, ?
Page<Board> findByIdGreaterThan(Long id, Pageable paging);
@Query(value = "select * from board b where b.username like %?1%", nativeQuery = true)
List<Board> findBoardByUsername(String username);
}
JPA
는 메소드의 이름
만으로 원하는 쿼리
를 실행하는 방법
을 제공합니다. 이때 쿼리는 select
에만 해당합니다.
쿼리 메소드는 다음과 같은 단어들로 시작합니다.
예를 들어, find...By...
을 사용하면 find 뒤에 엔티티 타입
을 지정합니다. Board
클래스라면 findBoardBy...
이 됩니다. 만약 타입을 지정하지 않으면, 현재 실행하는 Repository
의 타입 정보
를 기준으로 동작합니다.
여기선 JpaRepository<Board, Long>
의 Board
타입이 되겠죠👍?
By
뒤쪽에는 컬럼명
을 이용하여 구성합니다. 예를 들어 username
컬럼을 이용해 검색하려면 findBoardByUsername
이 됩니다.
쿼리 메소드의 리턴 타입은 Page<T>
, Slice<T>
, List<T>
와 같은 Collection<T>
형태가 됩니다.
쿼리 메소드 작성 방법은 여기서 확인 가능합니다.
테스트 코드를 통해 하고자 하는 것은 다음과 같습니다.
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Sort;
import org.springframework.test.context.junit4.SpringRunner;
import java.util.Collection;
import java.util.List;
@RunWith(SpringRunner.class)
@SpringBootTest
public class SpringbootMysqlBoardApplicationTests {
@Autowired
BoardRepository boardRepository;
@Test
public void insert10() {
for(int i = 0; i < 10; i++) {
Board board = Board.builder()
.username("testUser" + i)
.content("test")
.build();
boardRepository.save(board);
}
}
@Test
public void findByContent() {
boardRepository.findBoardByContent("test")
.forEach(board -> System.out.println(board));
}
@Test
public void testIdOrderByPaging() {
Pageable pageable = PageRequest.of(0, 5);
Collection<Board> boards = boardRepository.findByIdGreaterThanOrderByIdDesc(0l, pageable);
boards.forEach(board -> System.out.println(board));
}
@Test
public void testPagingSort() {
Pageable pageable = PageRequest.of(0, 5, Sort.Direction.DESC, "id");
Page<Board> result = boardRepository.findByIdGreaterThan(0L, pageable);
System.out.println("PAGE SIZE: " + result.getSize());
System.out.println("TOTAL PAGE: " + result.getTotalPages());
System.out.println("TOTAL COUNT: " + result.getTotalElements());
System.out.println("NEXT: " + result.nextPageable());
List<Board> list = result.getContent();
}
@Test
public void testJpaQueryByUsername() {
boardRepository.findBoardByUsername("testUser7")
.forEach(board -> System.out.println(board));
}
@Test
public void contextLoads() {
}
}
쿼리 메소드들에는 마지막 파라미터로 페이지 처리를 할 수 있는 Pageable 인터페이스
와 정렬을 처리하는 Sort 인터페이스
를 사용할 수 있습니다.
Pageable 인터페이스
는 말 그대로 페이징
처리에 필요한 정보를 제공합니다. 흔히 많이 사용하는 것은 org.springframework.data.domain.Pageable
인터페이스를 구현한 클래스 중 PageRequest
클래스를 이용합니다.
스프링 부트 2.0의 경우 new PageRequest()
는 deprecated
이기 때문에, PageRequest.of()
를 사용합니다.
Spring Data JPA에서 결과가 여러 개인 경우 List 타입을 이용하기도 하지만, Page 타입을 이용하면 상당히 편하게 페이징 할 수 있습니다.
public interface Page<T> extends Slice<T> {
static <T> Page<T> empty() {
return empty(Pageable.unpaged());
}
static <T> Page<T> empty(Pageable pageable) {
return new PageImpl(Collections.emptyList(), pageable, 0L);
}
int getTotalPages();
long getTotalElements();
<U> Page<U> map(Function<? super T, ? extends U> var1);
}
public interface Slice<T> extends Streamable<T> {
int getNumber();
int getSize();
int getNumberOfElements();
List<T> getContent();
boolean hasContent();
Sort getSort();
boolean isFirst();
boolean isLast();
boolean hasNext();
boolean hasPrevious();
default Pageable getPageable() {
return PageRequest.of(this.getNumber(), this.getSize(), this.getSort());
}
Pageable nextPageable();
Pageable previousPageable();
<U> Slice<U> map(Function<? super T, ? extends U> var1);
}
스프링부트에서 mysql을 연동하고 jpa를 이용한 crud 방법을 간단하게 알아보았습니다.
다음에는 동적SQL 처리를 위한 Querydsl을 알아보겠습니다.