SpringBoot Data JPA 시작 및 기본 환경설정 방법 알아보기
Spring Data JPA
정의
Spring Data 의 모듈 중 JPA를 사용하면 JPA 기반 저장소를 쉽게 구현할 수 있습니다.
이 모듈은 JPA 기반 데이터 액세스 계층에 대한 향상된 자원을 다루며, Spring 기반 애플리케이션을 더 쉽게 구축할 수 있습니다.
간단한 쿼리를 실행하고 데이터 쿼리를 실행하고 페이지를 보여주는 로직까지 많은 소스 코드를 작성해야 합니다.
Spring Data JPA는 데이터 액세스 계층의 구현을 크게 개선하는 것을 목표로 사용자 정의 파인더 메소드를 포함하여 저장소 인터페이스를 작성하면 Spring이 자동으로 구현을 제공합니다.
특징
1. Spring 및 JPA 기반의 레포지토리 구축을 위한 정교한 지원
2. Querydsl 지원
3. 동적 쿼리 실행, 맞춤형 데이터 액세스 코드 통합
4. xml 기반 엔티티 매핑 지원
5. JavaConfig 기반 저장소 구성 ( @EnableJpaRepositories )
장점
1) 생산성이 뛰어나고 유지보수가 용이하다.(데이터베이스 중심 설계에서 객체 중심 설계로 변경됨에 따른) - 객체 지향적인 코드로 인해 더 직관적이고 비즈니스 로직에 더 집중할 수 있게 도와준다. - 객체지향적으로 데이터를 관리할 수 있기 때문에 전체 프로그램 구조를 일관되게 유지할 수 있다. - SQL을 직접적으로 작성하지 않고 객체를 사용하여 동작하기 때문에 유지보수가 더욱 간결하고, 재사용성도 증가하여 유지보수가 편리해진다. - DB컬럼이 추가될 때마다 테이블 수정이나 SQL 수정하는 과정이 많이 줄어들고, 값을 할당하거나, 변수 선언등의 부수적인 코드 또한 급격히 줄어든다. - 각각의 객체에 대한 코드를 별도로 작성하여 코드의 가독성도 올라간다.
2) DBMS에 대한 종속성이 줄어든다. - DBMS가 변경된다 하더라도 소스, 쿼리, 구현 방법, 자료형 타입 등을 변경할 필요가 없다. - 즉 프로그래머는 Object에만 집중하면 되고, DBMS를 교체하는 작업에도 비교적 적은 리스크와 시간이 소요된다. 특히 요즘은 탈Oracle을 하여 MariaDB 등의 무료, 오픈소스 기반의 DMBS로 변경하는 기업이 늘고 있는데 이럴때 개발자들이 신경쓸 부분이 현저히 줄어든다.
단점
1) 어렵다. - JPA의 장점을 살려 잘 사용하려면 학습 비용이 높은 편이다. - 복잡한 쿼리를 사용해야 할 때에 불리하다. 업무 비즈니스가 매우 복잡한 경우 JPA로 처리하기 어렵고, 통계처리와 같은 복잡한 쿼리 자체를 ORM으로 표현하는데 한계가 있다. (실시간 처리용 쿼리에 더 최적화되어 있다고 봐도 무방할 것이다.) - 결국 기존 데이터베이스 중심으로 되어 있는 환경에서는 JPA를 사용하기도 어렵고, 힘을 발휘하기 어렵다. - 잘못사용할 경우 실제 SQL문을 직접 작성하는 것보다는 성능이 비교적 떨어질 수 있다. - 대용량 데이터 기반의 환경에서도 튜닝이 어려워 상대적으로 기존 방식보다 성능이 떨어질 수 있다.
결국 업무 환경, 이러한 장단점을 고려하여 Mybatis를 사용할지 JPA를 사용할지 의사결정에 참고하면 좋을 것 같다.
JPA 설정 방법
1. 의존성 추가
implementation 'org.springframework.boot:spring-boot-starter-data-jpa'
build.gradle 에서 dependencies jpa 프로젝트의 의존성을 추가한다.
2. Entity 클래스 생성
Entity가 설정된 Class는 JPA가 관리하는 클래스이고, 테이블과 매핑할 테이블은 어노테이션을 붙여 사용한다.MBR_NO 필드는 @ID 어노테이션을 사용하여 기본pk로 지정한다.
테이블 생성 시 해당 필드를 PK, AUTO_INCREMENT로 설정하였기 때문에 직접 할당 방식이 아닌, 자동으로 값이 생성되도록 하기 위해 @GeneratedValue 어노테이션을 사용한다.
@Data
@Entity(name="member")
public class MemberVo {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long mbrNo;
private String id;
private String name;
@SuppressWarnings("unused")
private MemberVo() {
}
@Builder
public MemberVo(String id, String name) {
this.id = id;
this.name = name;
}
}
3. Mysql 테이블 생성
GenerationType.IDENTITY는 기본 키 생성을 데이터베이스에 위임하는 방식이다.
CREATE TABLE IF NOT EXISTS TEST.MEMBER (
MBR_NO BIGINT NOT NULL AUTO_INCREMENT,
ID VARCHAR(200),
NAME VARCHAR(200),
PRIMARY KEY(MBR_NO) /*AUTO_INCREMENT 컬럼 단일 PK */
);
4. Repository 클래스 생성
JPA에서는 단순히 Repository 인터페이스를 생성 후 JpaRepository<Entity, 타입> 을 Extends 하면 기본적인 Create, Read, Update, Delete가 자동으로 생성된다.
인터페이스를 만들고, 상속을 잘 해주면 기본적인 동작 테스트가 가능하다.
JPA 처리를 담당하는 Repository는 기본적으로 4가지가 있다. (T : Entity의 타입클래스, ID : P.K 값의 Type)
1) Repository<T, ID>
2) CrudRepository<T, ID>
3) PagingAndSortingRepository<T, ID>
4) JpaRepository<T, ID>
@Repository
public interface MemberRepository extends JpaRepository<MemberVo, Long>{
// id 검색
public List<MemberVo> findById(String id);
// name 검색
public List<MemberVo> findByName(String name);
// like 검색
public List<MemberVo> findByNameLike(String keyword);
public List<MemberVo> findAll();
public Optional<MemberVo> findById(Long mgrNo);
public void deleteById(Long mbrNo);
}
5. Service 클래스 생성
@Service
public class MemberService {
@Autowired
private MemberRepository memberRepository;
public List<MemberVo> findAll(){
List<MemberVo> members = new ArrayList<>();
memberRepository.findAll().forEach(f -> members.add(f));
return members;
}
public Optional<MemberVo> findById(Long mbrNo) {
return memberRepository.findById(mbrNo);
}
@Transactional
public void deleteById(Long mbrNo) {
memberRepository.deleteById(mbrNo);
}
}
6. Controller 생성
@RestController
@RequestMapping("/members")
public class TestJpaRestController {
@SuppressWarnings("unused")
private final Logger logger = LoggerFactory.getLogger(this.getClass());
@Autowired
private MemberService memberService;
@GetMapping(value="/all", produces = { MediaType.APPLICATION_JSON_VALUE })
public ResponseEntity<List<MemberVo>> getAllData(){
List<MemberVo> member = memberService.findAll();
return new ResponseEntity<List<MemberVo>>(member, HttpStatus.OK);
}
@GetMapping(value="/{mbrNo}", produces = {MediaType.APPLICATION_JSON_VALUE})
public ResponseEntity<MemberVo> getByIdData(@PathVariable Long mbrNo){
Optional<MemberVo> member = memberService.findById(mbrNo);
return new ResponseEntity<MemberVo>(member.get(), HttpStatus.OK);
}
@DeleteMapping(value="/{mbrNo}", produces = {MediaType.APPLICATION_JSON_VALUE})
public ResponseEntity<Void> delMember(@PathVariable Long mgrNo){
memberService.deleteById(mgrNo);
return new ResponseEntity<Void>(HttpStatus.NO_CONTENT);
}
}
7. Properties 설정
#JPA 설정 #Dialect 설정 spring.jpa.properties.hibernate.dialect=org.hibernate.dialect.MariaDBDialect #하이버네이트가 실행하는 모든 SQL문을 콘솔로 출력해 준다. spring.jpa.properties.hibernate.show_sql=true #콘솔에 출력되는 JPA 실행 쿼리를 가독성있게 표현한다. spring.jpa.properties.hibernate.format_sql=true #디버깅이 용이하도록 SQL문 이외에 추가적인 정보를 출력해 준다. spring.jpa.properties.hibernate.use_sql_comments=true
기본적인 JPA 설정은 완료되었다.
SpringBoot를 실행하고 테스트 결과를 확인해보자