
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을 알아보겠습니다.