DB에 테이블에 대응하는 클래스
해당 클래스가 엔티티임 명시하며 테이블과 매핑된다.
클래스 이름과 테이블의 이름을 다르게 지정할 시 사용
기본키 역할 사용할 칼럼(필드) 설정
기본키 자동 생성방법 결정
엔티티 클래스 필드는 자동으로 칼럼 매핑
필드에 설정을 더할 때 사용
엔티티가 생성한 데이터베이스에 접근하는 데 사용
Spring Data JPA가 제공하는 인터페이스
JpaRepository를 상속받는다.
데이터베이스에 접근하기 위한 로직 관리 객체
인터페이스 - 구현체 방식으로 구현
Repository와 비슷한 역할
Repository의 메소드를 사용해 원하는 데로 로직 관리
단순 데이터 교환용 객체
빌더 패턴을 사용해 생성자 사용 시 유연성 확보 가능
DAO, Repository를 통해 핵심 기능을 전달하도록 구성
클라이언트로부터 요청을 받아 해당 요청에 대해 적절한 메서드를 호출해서 결과값을 받는다.
@Entity
@Table(name="product")
public class Product { // 엔티티 객체 메소드
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
private Long number;
@Column(nullable = false)
private String name;
@Column(nullable = false)
private Integer price;
@Column(nullable = false)
private Integer stock;
private LocalDateTime createAt;
private LocalDateTime updateAt;
public Long getNumber() {
return number;
}
public void setNumber(Long number) {
this.number = number;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Integer getPrice() {
return price;
}
public void setPrice(Integer price) {
this.price = price;
}
public Integer getStock() {
return stock;
}
public void setStock(Integer stock) {
this.stock = stock;
}
public LocalDateTime getCreateAt() {
return createAt;
}
public void setCreateAt(LocalDateTime createAt) {
this.createAt = createAt;
}
public LocalDateTime getUpdateAt() {
return updateAt;
}
public void setUpdateAt(LocalDateTime updateAt) {
this.updateAt = updateAt;
}
}
MySQL 사용 시 Boolean 타입이 없기 때문에 @Column
타입의 columnDefinition 값을 "TINYINT"로 설정해줘야 한다.
MySQL의 datetime 타입을 @Temporal
을 사용해 java.util.Date 타입으로 매핑해서 사용해야한다.
@Column(name="open_status", columnDefinition = "TINYINT", length=1)
@Temporal(TemporalType.TIMESTAMP)
private Date open_date = null;
public interface ProductRepository extends JpaRepository<Product,Long> { // JpaRepository 메소드 제공
}
@Component
public class ProductDAOImpl implements ProductDAO {
ProductRepository productRepository;
@Autowired
public ProductDAOImpl(ProductRepository productRepository){
this.productRepository = productRepository;
}
@Override
public Product insertProduct(Product product) {
Product savedProduct = productRepository.save(product);
return savedProduct;
}
@Override
public Product selectProduct(Long number) {
Product selectedProduct = productRepository.getReferenceById(number); // 해당 엔티티로 리턴
return selectedProduct;
}
@Override
public Product updateProductName(Long number, String name) throws Exception {
Optional<Product> selectedProduct = productRepository.findById(number);
Product updatedProduct;
if(selectedProduct.isPresent()){
Product product = selectedProduct.get();
product.setName(name);
product.setUpdateAt(LocalDateTime.now());
updatedProduct = productRepository.save(product);
}else {
throw new Exception();
}
return updatedProduct;
}
// getById 데이터 존재하지 않을 시 EntityNotFoundException 발생
// findById는 영속성 컨텍스트에 값이 없다면 실제 DB에서 데이터 조회
@Override
public void deleteProduct(Long number) throws Exception {
Optional<Product> selectedProduct = productRepository.findById(number);
if(selectedProduct.isPresent()){
Product product = selectedProduct.get();
productRepository.delete(product);
}else{
throw new Exception();
}
}
}
ProductDto
public class ProductDto {
private String name;
private int price;
private int stock;
}
ProductResponseDto
public class ProductResponseDto {
private Long number;
private String name;
private int price;
private int stock;
}
ChangeProductNameDto
public class ChangeProductNameDto {
private Long number;
private String name;
}
@Service
public class ProductServiceImpl implements ProductService {
private final ProductDAO productDAO;
@Autowired
public ProductServiceImpl(ProductDAO productDAO){
this.productDAO = productDAO;
}
@Override
public ProductResponseDto getProduct(Long number) {
Product product = productDAO.selectProduct(number);
ProductResponseDto productResponseDto = new ProductResponseDto();
productResponseDto.setNumber(product.getNumber());
productResponseDto.setName(product.getName());
productResponseDto.setPrice(product.getPrice());
productResponseDto.setStock(product.getStock());
return productResponseDto;
}
@Override
public void saveProduct(ProductDto productDto) {
Product product = new Product();
product.setName(productDto.getName());
product.setPrice(productDto.getPrice());
product.setStock(productDto.getStock());
product.setCreateAt(LocalDateTime.now());
product.setUpdateAt(LocalDateTime.now());
Product savedProduct = productDAO.insertProduct(product);
}
@Override
public void changeProductName(Long number, String name) throws Exception {
Product changedProduct = productDAO.updateProductName(number, name);
}
@Override
public void deleteProduct(Long number) throws Exception {
productDAO.deleteProduct(number);
}
}
@RestController
@RequestMapping("/product")
public class ProductController {
private final ProductService productService;
@Autowired
public ProductController(ProductService productService){
this.productService = productService;
}
@GetMapping()
public ResponseEntity<ProductResponseDto> getProduct(Long number){
ProductResponseDto productResponseDto = productService.getProduct(number);
return ResponseEntity.status(HttpStatus.OK).body(productResponseDto);
}
@PostMapping()
public ResponseEntity<ProductResponseDto> createProduct(@RequestBody ProductDto productDto){
ProductResponseDto productResponseDto = productService.saveProduct(productDto);
return ResponseEntity.status(HttpStatus.OK).body(productResponseDto);
}
@PutMapping()
public ResponseEntity<ProductResponseDto> changeProductName(
@RequestBody ChangeProductNameDto changeProductNameDto) throws Exception {
ProductResponseDto productResponseDto = productService.changeProductName(
changeProductNameDto.getNumber(), changeProductNameDto.getName()
);
return ResponseEntity.status(HttpStatus.OK).body(productResponseDto);
}
@DeleteMapping()
public ResponseEntity<String> deleteProduct(Long number) throws Exception{
productService.deleteProduct(number);
return ResponseEntity.status(HttpStatus.OK).body("정상 삭제되었습니다.");
}
}
@Autowired
까먹지 말기 (30분 날렸다.)
2022.08.10 수정완료