Spring Boot+JPA REST API 서버 만들기
Spring Boot + Gradle + JPA
Spring Boot로 REST API 서버를 만들어보자
클라이언트는 ios, android, web으로 가정한다.
ide : IntelliJ IDEA 2017.1.2
spring boot : 1.5.3.RELEASE
build : gradle
github : https://github.com/kkashio/springboot-rest-server.git
디렉토리 구조
Gradle
dependencies {
compile('org.springframework.boot:spring-boot-starter-data-jpa')
compile('org.springframework.boot:spring-boot-starter-web')
runtime('com.h2database:h2')
compileOnly('org.projectlombok:lombok')
testCompile('org.springframework.boot:spring-boot-starter-test')
}
JPA를 사용하기 위해 간단하게 나마 DB 모델링을 해야한다.
게시판과 멤버 테이블을 간단히 모델링 해보았다.
위에 모델링을 참고하여 domain class를 만들어보자
Member.java
@Entity(name = "MEMBER")
@Data
@AllArgsConstructor
@NoArgsConstructor
public class Member {
@Id
@Column(name = "EMAIL")
private String email;
@Column(name = "PASSWORD")
private String password;
@Column(name = "NICKNAME")
private String nickname;
@Column(name = "REG_DATE")
private Date regDate;
}
@Entity - 해당 클래스를 엔티티로 정의
@Data - lombok의 getter/setter
@AllArgsConstructor, @NoArgsConstructor - 자동 생성자
@Id - PK 지정
Board.java
@Entity(name = "BOARD")
@Data
@AllArgsConstructor
@NoArgsConstructor
public class Board {
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
@Column(name = "BOARD_ID")
private long id;
@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "EMAIL")
private Member member;
@Column(name = "TITLE")
private String title;
@Column(name = "CONTENT")
private String content;
@Column(name = "REG_DATE")
private Date regDate;
@Column(name = "MODIFY_DATE")
private Date modifyDate;
@Column(name = "DEL_FLAG")
private boolean delFlag;
}
@GeneratedValue - 아이디 값 자동 할당
strategy 값으로
- AUTO (기본값) : 데이터베이스에 따라 자동으로 선택
- IDENTITY : 기본키 생성을 DB에 위임하는 방법 (MySql, PostgresSQL, SQL Server, DB2)
- SEQUENCE : DB 시퀀스를 사용해 기본 키를 할당하는 방법 (Oracle, PostgresSQL, DB2, H2)
- TABLE : 키 생성 테이블을 사용하는 방법
이제 JpaRepository를 상속받은 repository interface를 구현해보자
BoardRepository
public interface BoardRepository extends JpaRepository<Board, Long>{
Stream<Board> findByMember(String email);
}
기본적으로 JpaRepository만 상속 받으면 기본적인 CRUD를 사용할 수 있다. JpaRepository 클래스를 좀 더 상세히보면 CrudRepository를 상속받고 있어 기본적인 findAll, findOne, save 등 CRUD를 할 수 있다.
또한 Query Method를 이용해 원하는 데이터값을 불러 올 수 있다.
위의 경우 findByMember로 Board 엔티티의 멤버를 이용해 게시목록을 얻어오는 기능이다.
MemberRepository
public interface MemberRepository extends JpaRepository<Member, String>{
List<Member> findByNickname(String nickname);
}
findByNickname : Member 엔티티에서 닉네임으로 유저목록을 가지고 오는 기능이다.
게시판의 경우 자바8의 Stream 형태로 리턴받고, 밑은 일반적으로 많이 쓰는 List로 리턴받는다.
간단한 비지니스 로직을 추가하기 위해 Service단을 만들어보자.
BoardService
public interface BoardService {
List<Board> findByWriter(String email);
}
먼저 인터페이스로 필요한 메서드를 정의하고
BoardServiceImpl
@Service
public class BoardServiceImpl implements BoardService {
@Autowired
BoardRepository boardRepository;
@Override
@Transactional
public List<Board> findByWriter(String email) {
return boardRepository.findByMember(email).collect(Collectors.toList());
}
}
@Service - BoardService를 Bean에 등록해준다.
@Autowired - 등록된 Bean을 사용
@Transactional - 메서드 트랙잭션 설정 ( 이 기능은 사용하지 않아도 무방하나 추후 따로 설명을 하겠습니다. - 영속성 관련 )
구현 클래스에서 BoardService를 구현한다.
findByWriter은 글쓴이로 게시목록을 찾는 기능이다.
boardRepository의 findByMember의 기능을 이용하였고 Stream으로 리턴받은 값을 List로 바꾸어 리턴해주었다. ( Stream은 기능은 따로 정리 하겠습니다 )
MemberService
public interface MemberService {
List<Member> findAll();
}
MemberServiceImpl
@Service
public class MemberServiceImpl implements MemberService {
@Autowired
MemberRepository memberRepository;
@Override
public List<Member> findAll() {
return memberRepository.findAll();
}
}
여기선 JpaRepository의 기본기능인 findAll 사용함
BoardController
@RestController
@RequestMapping("/board")
public class BoardController {
@Autowired
BoardService boardService;
@GetMapping("/writer/{email}")
public List<Board> findByWriter(@PathVariable String email){
return boardService.findByWriter(email);
}
}
@RestController - 해당 클래스를 RestController로 만듬 ( 다음 요청을 리턴은 body에 데이터를 실어 리턴 )
@RequestMapping - 맵핑되는 url
@GetMapping - Type이 GET인 맵핑
@PathVariable - url에 { } 에 들어간 값을 파싱해온다. 변수 이름과 파싱해올 데이터 이름이 다르면 따로 선언해주어야한다.
BASE_URL + /board/writer/{email} 로 요청을 하면 해당 메서드가 실행된다.
MemberController
@RestController
@RequestMapping("/member")
public class MemberController {
@Autowired
MemberService memberService;
public List<Member> findAll(){
return memberService.findAll();
}
}
BASE_URL+/member
DB에 등록된 모든 member를 불러온다.