[SpringBoot] 4. JPA를 활용한 DB 연결(feat.@RestController) - 이미 존재하는 데이터를 가져오기
어떤 프로젝트를 만들것인가?
OracleDB에 존재하는 products 테이블의 데이터를 JPA를 통해 불러오자!
그럼 이제 결과 페이지가 나오기까지의 과정을 함께해봅시다!
그리고 여전히 틀린 정보 속출 가능 주의
사전작업
이번엔 myBatis가 아닌, JPA를 사용할 것이기 때문에 프로젝트 Dependencies는 이렇게 선택했습니다.
(생각해보니 여기서 쓸 글에는 타임리프가 딱히 필요하진 않네요ㅎ)
그리고 프로젝트 실행에 필요한 파일은 지난 글의 내용을 재탕하자면..
위와 같기 때문에 src/main/java 경로에는 총 네 개의 파일이 필요합니다.
파일명은 알아서 하십쇼..
1. Model(혹은 vo) : Products.java
2. Repository 인터페이스 : ProductsRepository.java
3. Service : ProductService.java
4. Controller : ProductController.java
myBatis를 사용할 때와는 다르게, mapper가 사라지고 repository라는 새로운 녀석이 나타났네요.
view에 해당하는 resource 폴더에 들어갈 파일(.html)은 이번 글에서는 필요하지 않을듯 합니다.
이유는 뒤에서~
마지막으로 각자 상황에 맞게 포트번호, db연결 옵션, 쿼리 출력 옵션 등등...
application.properties까지 설정하면 사전작업은 끝입니다
1. Model(혹은 vo) : Products.java
package com.example.springdb.vo;
import jakarta.persistence.*;
import lombok.Getter;
import lombok.Setter;
@Entity
@Getter @Setter
public class Products {
/*
PRODUCT_ID NUMBER(5,0)
PRODUCT_NAME VARCHAR2(100 BYTE)
CATEGORY VARCHAR2(50 BYTE)
PRICE NUMBER(10,2)
STOCK_QUANTITY NUMBER(5,0)
*/
//멤버(필드)변수
@Id
private Long product_id;
private String product_name;
private String category;
private Long price;
private Long stock_quantity;
}
Getter와 Setter는 lombok을 통해서 생성했습니다
사실 이 친구도 일단은 그냥 테이블을 매핑하는 목적이라 Getter, Setter까진 필요없긴하네요 암튼
그리고 @Entity 어노테이션 및 @Id를 통해 테이블 매핑 및 PK지정까지 해줬습니다.
최소한 이 두 가지는 써줘야 아무리 이미 존재하는 데이터라도 인식을 할 수 있습니다. JPA는 이 둘을 통해 객체를 구분하기 때문입니다.
(존재하지 않는 데이터를 직접 생성하는 것에 대해서는 다른 글에서...)
2. Repository : ProductRepository.java
package com.example.springdb.repository;
import org.springframework.data.jpa.repository.JpaRepository;
import com.example.springdb.vo.Products;
public interface ProductRepository extends JpaRepository<Products, Long>{
}
인터페이스를 생성하고 JPA 사용을 위해 JpaRepository를 적용합니다.
myBatis를 사용할 때와 비교하자면 이 친구가 mapper.xml 및 mapper.java 역할을 한다고 볼 수 있는데...
뭔가 많이 생략됐습니다.
여기서 JPA의 강력한 편리함을 알 수 있습니다. 여기에 내장된 메서드들로 개발자들이 굳이 SQL쿼리를 작성하지 않아도 데이터를 조작할 수 있거든요. 기본적인 CRUD 기능은 다 할 수 있다고 보면 될 것같습니다.
하지만 편리한만큼 다소 복잡한 쿼리를 다루기에는 좋지 않아요. 그러니 상황에 따라 적당한 방법을 택하시길 ㅎ
3. Service : ProductService.java
package com.example.springdb.service;
import java.util.List;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import com.example.springdb.repository.ProductRepository;
import com.example.springdb.vo.Products;
@Service
public class ProductService {
@Autowired
private final ProductRepository productRepository;
public ProductService(ProductRepository productRepository) {
this.productRepository = productRepository;
}
//테이블 내 모든 상품을 조회하는 서비스
public List<Products> getAllProducts(){
return productRepository.findAll();
}
}
레퍼지토리에서 상황에 적절한 쿼리가 담겨있는 메서드를 가지고와서 지정했습니다.
이때 productRepository.findAll( )에서 findAll이 매핑된 테이블의 전체 데이터를 조회하는 SELECT문이 내장된 메서드입니다. 이에 대한 종류도 따로 글을 써봐야겠어요 휴
4. Controller : ProductController.java
package com.example.springdb.controller;
import java.util.List;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import com.example.springdb.service.ProductService;
import com.example.springdb.vo.Products;
@RestController
@RequestMapping("/products")
public class ProductController {
@Autowired
private ProductService productService;
//테이블 내 모든 상품을 조회하는 메서드
@GetMapping
public List<Products> getAllProducts(Model model) {
List<Products> products = productService.getAllProducts();
return products;
}
}
여기서 등장하는 개념이 바로 @RestController입니다
생긴것은 @Controller와 비슷하게 생겼지만 하는 역할은 꽤나 다릅니다.
그동안 @Controller로 선언된 클래스는 항상 view 역할을 하는 .html 파일을 매핑해서 사용자에게 보여주는 역할을 했습니다.
하지만 @RestController같은 경우는, 사용자 맞춤이라기보다는 데이터 그 자체를 반환하는 역할을 합니다.
그래서 이를 실행하고 브라우저를 확인하면?
이러한 창이 보일 것입니다.
어떻게 .html 파일이 없는데 이런 결과를 볼 수 있을까요?
바로 @RestController로 선언된 클래스는 return으로 받는 값을 html 파일 호출이 아닌, 데이터 그 자체로 인식하기 때문입니다.
그래서 @Controller로 실행되는 페이지의 경우, 페이지 자체를 저장하려고 하면
이렇게 파일 형식이 '웹페이지'로 인식되지만
.
.
.
@RestController의 경우에는
이렇게 JSON 파일로 인식을 합니다.
이렇게 오늘은 처음으로
JPA를 통해 직접적인 쿼리 작성 없이 데이터를 조회할 수 있는 프로젝트를 만들어봤습니다.
그런데 몇 번 JPA를 활용하다보니 느낀 점이 있는데...
1. 다소 부정확한 데이터 인식
2. 데이터 반영이 굉장히 느림
이라는 점에서.. 역시 마냥 편한게 좋은건 아니구나 싶었습니다.
이것도 컴퓨터 사양이나 다른 환경에 따라 달라질 수는 있겠지만요
확실히 복잡한 쿼리 작성이 필요할 때는 myBatis가 우선이 되지 않을까 생각해보게 됐습니다.