상세 컨텐츠

본문 제목

[스프링 1팀] 6장 데이터베이스 연동

24-25/Spring 1

by oze 2024. 11. 29. 10:00

본문

728x90

 

 

데이터베이스 연동

프로젝트 생성(5장과 동일) 

 

 

Swagger 설정(5.6절과 동일 - 변경사항 있음)

📌Spring Boot 버전 3.x.x 이상부터는 기존 SpringFox 호환 안됨

      따라서 pom.xml파일에 아래와 같이 swagger 의존성 추가

// jpa/pom.xml

<dependencies>
    ...
    <dependency>
    	  <groupId>org.springdoc</groupId>
	  <artifactId>springdoc-openapi-starter-webmvc-ui</artifactId>
	  <version>2.0.2</version>
    </dependency>
    ...
  </dependencies>

 

📌마찬가지로 SwaggerConfiguration도 다음과 같이 설정

config/SwaggerCofiguration.java

@Configuration
public class SwaggerConfiguration {

    @Bean
    public OpenAPI openAPI() {
        return new OpenAPI()
                .components(new Components())
                .info(apiInfo());
    }

    private Info apiInfo() {
        return new Info()
                .title("Spring Boot JPA Documentation")
                .description("스프링 부트 JPA 문서")
                .version("1.0");
    }
}

 

application.properties 설정

Spring Data JPA 의존성을 추가한 후 연동할 데이터 베이스의 정보를 작성해야 함

application.properties

// 데이터 베이스를 연동하는 설정
spring.datasource.driverClassName=org.mariadb.jdbc.Driver 
spring.datasource.url=jdbc:mariadb://localhost:3307/springboot  
spring.datasource.username=root 
spring.datasource.password=비밀번호  

// 하이버네이트와 관련된 선택사항
spring.jpa.hibernate.ddl-auto=create  
spring.jpa.show-sql=true
spring.jpa.properties.hibernate.format_sql=true

 

ddl-auto: 데이터베이스를 자동으로 저작하는 옵션

* 사용가능한 다른 옵션

  • create: 애플리케이션 가동 후 SessionFactory가 실행될 때 기존 테이블을 지우고 새로 생성함
  • create-drop: create와 동일한 기능을 수행하나, 애플리케이션을 종료하는 시점에서 테이블을 지움
  • update: SesstionFactory가 실행될 때 객체를 검사해서 변경된 스키마를 갱신. 기존의 저장된 데이터는 유지
  • validate: update처럼 객체를 검사하지만 스키마는 건드리지 않음. 검사 과정에서 데이터베이스의 테이블 정보와 객체의 정보가 다르면 에러 발생
  • none: ddl-auto 기능 사용 안함

=> 운영환경: validate나 none 사용 

=> 개발환경: create나 update 사용

 

 

 

엔티티 설계

Spring Data JPA를 사용하면 데이터베이스에 테이블을 생성하기 위해 직접 쿼리를 작성할 필요 없음

이 기능을 가능하게 하는 것이 바로 엔티티

 

엔티티

JPA에서 엔티티는 데이터베이스의 테이블에 대응하는 클래스로, 엔티티에는 데이터베이스에 쓰일 테이블과 칼럼을 정의함. 엔티티에 어노테이션을 사용하면 테이블 간의 연관관계를 정의할 수 있음

 

아래 테이블을 간단하게 엔티티 클래스로 구현가능함

 

상품 테이블
상품 번호 int
상품 이름 varchar
상품 가격 int
상품 재고 int
상품 생성 일자 DateTime
상품 정보 변경 일자 DateTime

data/entity/Product.java

import lombok.Getter;
import lombok.Setter;
import jakarta.persistence.*;
import java.time.LocalDateTime;

@Entity
@Table(name="product")
@Getter
@Setter
public class Product {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    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;
    
    ... getter/setter 메서드 생략 ...
}

 

application.properties에 정의한 spring.jpa.hibernate.ddl-auto의 값을 create로 설정하면 쿼리문을 작성하지 않아도 데이터베이스에 테이블이 자동으로 만들어짐

 

 

엔티티 관련 기본 어노테이션

 

@Entity

해당 클래스가 엔티티임을 명시하기 위한 어노테이션

클래스 자체는 테이블과 일대일로 매칭되며, 해당 클래스의 인스턴스는 매핑되는 테이블에서 하나의 레코드를 의미함

 

@Table

테이블과 클래스의 이름을 다르게 지정할 때 사용

보통 엔티티 클래스는 테이블과 매핑되므로, 특별한 경우가 아니면 이 어노테이션은 필요 없음

서로 다른 이름을 쓰려면 @Table(name = 값) 형태로 데이터베이스의 테이블명을 따로 명시해야 함

 

@Id

엔티티 클래스의 필드는 테이블의 칼럼과 매핑. 이 어노테이션이 선언된 필드는 테이블의 기본값 역할로 사용됨

모든 엔티티는 @Id 어노테이션이 필요함

 

@GeneratedValue

해당 필드의 값을 어떤 방식으로 자동으로 생성할지 결정할 때 사용함(일반적으로 @Id 어노테이션과 함께 사용)

   

   📌 값 생성방식

  • @GeneratedValue를 사용하지 않는 방식(직접 할당): 애플리케이션에서 자체적으로 고유한 기본값을 생성할 경우
    => 내부에 정해진 규칙에 의해 기본값을 생성하고 식별자로 사용함
  • AUTO:  @GeneratedValue의 기본 설정값. 기본값을 사용하는 DB에 맞게 자동 생성함
  • IDENTITY: 기본값 생성을 DB에 위임하는 방식. DB의 AUTO_INCREMENT를 사용해 기본값을 생성함
  • SEQUENCE: @SequenceGenerator 어노테이션으로 식별자 생성기를 설정하고 이를 통해 값을 자동 주입받음
  • TABLE: 어떤 DBMS를 사용해도 동일하게 동작하기를 원할 경우 사용함. 식별자로 사용할 숫자의 보관 테이블을 별도로 생성하여 엔티티를 생성할 때마다 값을 갱신하면 사용함

@Column

필드에 몇 가지 설정을 더할 때 사용함

(엔티티 클래스의 필드는 자동으로 테이블 칼럼으로 매핑됨. 따라서 별다른 설정을 안 한다면 이 어노테이션 필요 없음)

  • name: DB의 칼럼명을 설정하는 속성(명시하지 않으면 필드명으로 지정)
  • nullable: 레코드 생성 시 칼럼 값에 null 처리가 가능한지를 명시하는 속성
  • length: DB에 저장하는 데이터의 최대 길이를 설정함
  • unique: 해당 칼럼을 유니크로 설정함

@Transient

엔티티 클래스에는 선언되어 있는 필드지만 DB에서는 필요 없을 경우, 이 어노테이션을 사용하여 DB에서 이용하지 않게 할 수 있음

 

 

 

리포지토리 인터페이스 설계 

Spring Data JPA는 JpaRepository를 기반으로 더욱 쉽게 DB를 사용할 수 있는 아키텍처를 제공

(스프링 부트로 JpaRepository를 상속하는 인터페이스를 생성하면, 기존의 다양한 메서드를 손쉽게 활용 가능)

 

리포지토리 인터페이스 생성

📌리포지토리 Spring Data JPA가 제공하는 인터페이스로 엔티티가 생성한 DB에 접근하는 데 사용됨

 

리포지토리를 생성하려면 접근하려는 테이블과 매핑되는 엔티티에 대한 인터페이스 생성 후 JpaRepository 상속받으면 됨

(이때, 대상 엔티티(Product)와 기본값 타입(Long)을 지정해야 함)

이렇게 하면 별도의 메서드 구현 없이도 많은 기능이 제공됨

 

data/repository/ProductRepository.java

public interface ProductRepository extends JpaRepository<Product, Long> { }

 

 

 

리포지토리 메서드의 생성 규칙

  • 메서드에 이름을 붙일 때는 첫 단어를 제외한 이후 단어들의 첫 글자를 대문자로 설정
  • FindBy: SQL문의 where 절 역할을 수행하는 구문으로, findBy 뒤에 엔티티의 필드값을 입력해서 사용
  • AND, OR: 조건을 여러 개 설정하기 위해 사용
  • Like, NotLike: SQL문의 like와 동일한 기능을 수행하며, 특정 문자를 포함하는지 여부를 조건으로 추가함
  • StartsWith/StartingWith: 특정 키워드로 시작하는 문자열 조건을 설정
  • EndsWith/EndingWith: 특정 키워드로 끝나는 문자열 조건을 설정
  • IsNull/IsNotNull: 레코드 값이 널이거나 널이 아닌 값을 검색
  • True/False: Boolean 타입의 레코드를 검색할 때 사용
  • Before/After: 시간을 기준으로 값을 검색
  • LessThan/GreaterThan: 특정 값을 기준으로 대소 비교를 할 때 사용
  • Between: 두 값(숫자) 사이의 데이터를 조회
  • OrderBy: SQL문에서 order by와 동일한 기능을 수행
  • countBy: SQL문의 count와 동일한 기능을 수행하며, 결괏값의 개수를 추출

 

DAO 설계

📌DAO(Data Access Object)

DB에 접근하기 위한 로직을 관리하는 객체로, 비즈니스 로직의 동작 과정에서 데이터를 조작하는 기능을 수행함

(다만, 스프링 데이터 JPA에서 DAO의 개념은 리포지토리가 대체하고 있음)

 

DAO 클래스 생성

DAO 클래스는 일반적으로 '인터페이스 - 구현체' 구성으로 생성함.

의존성 결합을 낮추기 위한 디자인 패턴으로, 서비스 레이어에 DAO 객체를 주입받을 때 인터페이스를 선언하는 방식으로 구성함.

 

  • ProductDAO 인터페이스 (data/dao/ProductDAO.java)
package com.springboot.jpa.data.dao;

import com.springboot.jpa.data.entity.Product;

public interface ProductDAO {
    Product insertProduct(Product product);
    Product selectProduct(Long number);
    Product updateProductName(Long number, String name) throws Exception;
    void deleteProduct(Long number) throws Exception;
}

 

일반적으로 DB에 접근하는 메서드는 리턴 값으로 데이터 객체를 전달함. 이때 데이터 객체를 엔터티 객체로 할지, DTO 객체로 할지는 개발자마다 입장 다름

일반적인 설계 원칙: 엔티티 객체는 DB에 접근하는 계층에서만 사용하도록 정의하고, 다른 계층으로 데이터를 전달할 때는 DTO 객체를 사용함 

 

  • ProductDAO 인터페이스의 구현체 클래스 (data/dao/impl/ProductDAOImpl.java)
package com.springboot.jpa.data.dao.impl;

import com.springboot.jpa.data.dao.ProductDAO;
import com.springboot.jpa.data.entity.Product;
import com.springboot.jpa.data.repository.ProductRepository;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.time.LocalDateTime;
import java.util.Optional;

@Component // 스프링 빈 등록
public class ProductDAOImpl implements ProductDAO {

	// DAO 객체가 DB에 접근하기 위해 리포지토리 인터페이스를 사용해 의존성을 주입 받음
    private final ProductRepository productRepository;

    @Autowired
    public ProductDAOImpl(ProductRepository productRepository){
        this.productRepository = productRepository;
    }

	// 인터페이스를 정의한 메서드 구현
    @Override
    public Product insertProduct(Product product) {  // Product 엔티티를 DB에 저장
        Product savedProduct = productRepository.save(product);

        return savedProduct;
    }

    @Override
    public Product selectProduct(Long number) { // 조회 메서드
        Product savedProduct = productRepository.getById(number); 

        return savedProduct;
    }

    @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;
    }

    @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();
        }

    }
}

 

  • ProductDAOImpl 클래스를 스프링이 관리하는 빈으로 등록하려면, @Component 또는 @Service 어노테이션을 지정=> 다른 클래스가 인터페이스를 가지고 의존성을 주입받을 때 이 구현체를 찾아 주입함
  • insertProduct():  Product 엔티티를 DB에 저장하는 기능을 수행함
    (리포지토리를 생성할 때, 인터페이스에서 따로 메서드를 구현하지 않아도 JPA에서 기본 메서드를 제공하므로 save 메서드를 활용하여 작성 가능)
  • selectProduct(): 조회메서드(리포지토리의 메서드 getById()를 이용)
  • updateProductName(): Product 데이터의 상품명을 업데이트함
    JPA는 값을 갱신할 때 update 키워드를 사용하지 않음. 영속성 컨텍스트를 활용해 값을 갱신하는데, find() 메서드를 통해 DB에서 값을 가져오면 가져온 객체가 영속성 컨텍스트에 추가됨. 영속성 컨텍스트가 유지되는 상황에서 객체의 값을 변경하고 다시 save()를 실행하면, JPA는 더티체크라고 하는 변경 감지를 수행함. 변경이 감지되면, 대상 객체에 해당하는 데이터베이스의 레코드를 업데이트하는 쿼리가 실행됨.
  •  deleteProduct(): 삭제 메서드
    findById()를 통해 삭제하려는 레코드와 매핑된 영속 객체를 영속성 컨텍스트에 가져오는 작업을 수행하고, delete() 메서드를 통해 해당 객체를 삭제함

DAO 연동을 위한 컨트롤러와 서비스 설계

앞서 설계한 구성 요소들을 클라이언트의 요청과 연결하려면 컨트롤러와 서비스를 생성해야 함. 

이를 위해 먼저 DAO의 메서드를 호출하고 그 외 비즈니스 로직을 수행하는 서비스 레이어를 생성한 후, 컨트롤러를 생성하도록 함.

 

서비스 클래스 만들기

서비스 레이어에서는 도메인 모델을 활용해 애플리케이션에서 제공하는 핵심 기능을 제공함

 

① DTO 클래스 작성

  • ProductDto 클래스(data/dto/ProductDto.java) 
package com.springboot.jpa.data.dto;

import lombok.Getter;
import lombok.Setter;

@Getter
@Setter
public class ProductDto {

    private String name;
    private int price;
    private int stock;

    public ProductDto(String name, int price, int stock){
        this.name = name;
        this.price = price;
        this.stock = stock;
    }
    
    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public int getPrice() {
        return price;
    }

    public void setPrice(int price) {
        this.price = price;
    }

    public int getStock() {
        return stock;
    }

    public void setStock(int stock) {
        this.stock = stock;
    }
}

 

  • ProductResponseDto 클래스 (data/dto/ProductResponseDto.java)
package com.springboot.jpa.data.dto;

import lombok.AllArgsConstructor;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter;

@Getter
@Setter
@NoArgsConstructor
@AllArgsConstructor

public class ProductResponseDto {
    private Long number;
    private String name;
    private int price;
    private int stock;

    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 int getPrice() {
        return price;
    }

    public void setPrice(int price) {
        this.price = price;
    }

    public int getStock() {
        return stock;
    }

    public void setStock(int stock) {
        this.stock = stock;
    }
}

 

 

② 서비스 인터페이스 작성

  • ProductService 인터페이스 (service/ProductService.java)
package com.springboot.jpa.service;

import com.springboot.jpa.data.dto.ProductDto;
import com.springboot.jpa.data.dto.ProductResponseDto;

public interface ProductService {

    ProductResponseDto getProduct(Long number);
    ProductResponseDto saveProduct(ProductDto productDto);
    ProductResponseDto changeProductName(Long number, String name) throws Exception;
    void deleteProduct(Long number) throws Exception;
}

 

위 인터페이스는 DAO에서 구현한 기능을 서비스 인터페이스에서 호출해 결괏값을 가져오는 작업을 수행하도록 설계함

(서비스에서는 클라이언트가 요청한 데이터를 가공해서 컨트롤러에게 넘김)

- 리턴 타입이 DTO 객체임 => 서비스 레이어에서 DTO 객체와 앤티티 객체를 각 레이어에 변환해서 전달하는 역할도 수행.

 

 

  • 서비스 인터페이스 구현체 클래스 (service/impl/ProductServiceImpl.java)
package com.springboot.jpa.service.impl;

import com.springboot.jpa.data.dao.ProductDAO;
import com.springboot.jpa.data.dto.ProductDto;
import com.springboot.jpa.data.dto.ProductResponseDto;
import com.springboot.jpa.data.entity.Product;
import com.springboot.jpa.service.ProductService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.time.LocalDateTime;

@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 ProductResponseDto saveProduct(ProductDto productDto) {   // 저장 메서드
        Product product = new Product();
        product.setName(productDto.getName());
        product.setPrice(productDto.getPrice());
        product.setStock(productDto.getStock());
        product.setUpdateAt(LocalDateTime.now());
        product.setCreateAt(LocalDateTime.now());

        Product savedProduct = productDAO.insertProduct(product);

        ProductResponseDto productResponseDto = new ProductResponseDto();
        productResponseDto.setStock(savedProduct.getStock());
        productResponseDto.setName(savedProduct.getName());
        productResponseDto.setNumber(savedProduct.getNumber());
        productResponseDto.setPrice(savedProduct.getPrice());

        return productResponseDto;
    }

    @Override
    public ProductResponseDto changeProductName(Long number, String name) throws Exception{   // 업데이트 메서드(상품정보 중 이름 변경)
        Product changeProduct = productDAO.updateProductName(number, name);

        ProductResponseDto productResponseDto = new ProductResponseDto();
        productResponseDto.setNumber(changeProduct.getNumber());
        productResponseDto.setName(changeProduct.getName());
        productResponseDto.setStock(changeProduct.getStock());
        productResponseDto.setPrice(changeProduct.getPrice());

        return productResponseDto;
    }

    @Override
    public void deleteProduct(Long number) throws Exception{    // 상품 삭제 메서드
        productDAO.deleteProduct(number);
    }
}

 

 

  • getProduct(): 현재 서비스 레이어에는 DTO 객체와 엔티티 객체가 공존하여 변환 작업이 필요.
    현재 코드에서는 DTO 객체를 생성하고 값을 넣어 초기화하는데, 이런 부분은 빌드 패턴을 활용하거나 엔티티 객체나 DTO 객체 내부에 변환하는 메서드를 추가해 간단하게 전환 가능
  •  saveProduct(): 전달받은 DTO객체를 통해 엔티티 객체를 생성해서 초기화 한 후, DAO 객체로 전달
    일반적으로 저장 메서드는 void 타입이나 boolean 타입으로 지정하는 경우가 많은데, 리턴 타입은 해당 비즈니스 로직이 어떤 성격을 띠느냐에 따라 결정하는 것이 바람직함
  •  changeProductName(): 이름을 변경하기 위해 대상을 식별할 수 있는 인덱스 값과 변경하려는 이름을 받아옴
  • deleteProduct():리포지터리에서 제공하는 delete()를 이용할 경우 리턴받는 타입이 지정되어있지 않기 때문에 void로 지정

 

컨트롤러 생성

서비스 객체의 설계를 마친 후에는 비즈니스 로직과 클라이언트 요청을 연결하는 컨트롤러를 생성함

(+ 컨트롤러에서 사용할 ChangeProductNameDtro도 생성) 

 

  • ProductController 클래스 (controller/ProductController.java)
// controller/ProductController.java

package com.springboot.jpa.controller;

import com.springboot.jpa.data.dto.ChangeProductNameDto;
import com.springboot.jpa.data.dto.ProductDto;
import com.springboot.jpa.data.dto.ProductResponseDto;
import com.springboot.jpa.service.ProductService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;

@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("정상적으로 삭제되었습니다.");
    }
}

 

  • ChangeProductNameDto 클래스 (data/dto/ChangeProductNameDto.java)
package com.springboot.jpa.data.dto;

import lombok.Getter;
import lombok.Setter;

@Getter
@Setter
public class ChangeProductNameDto {
    private Long number;
    private String name;
}

 

 

Swagger API를 통한 동작 확인

 

📌애플리케이션 실행 후 http://localhost:8080/swagger-ui/index.html 로 접속

 

 

상품 정보 저장

createProduct() 메서드 사용

 

 

상품 정보 조회

createProduct() 메서드 사용

 

상품 정보 변경

updateProductName() 메서드 사용

Swagger에서 Boby에 식별자 번호와 바꾸고자 하는 이름 기입

 

 

상품 정보 삭제

deleteProduct() 사용

삭제하려는 number값을 파라미터에 입력

 

 

반복되는 코드의 작성을 생략하는 방법 - 롬복

롬복(Lombok)

데이터(모델) 클래스를 생성할 때 반복적으로 사용하는 getter/setter 같은 메서드를 어노테이션으로 대체하는 기능을 제공하는 라이브러리

 

📌 장점

  • 어노테이션 기반의 코드 자동 생성 => 생산성 높아짐
  • 반복되는 코드 생략 가능 => 가독성 좋아짐
  • 롬복을 알면 간단하게 코드 유추 가능 => 유지보수에 용이

 

 

 

 

 

QUIZ

1. JPA에서 (     엔티티     )는 DB의 테이블에 대응하는 클래스로, DB에 쓰일 테이블과 칼럼을 정의한다.
2. 모든 엔티티에 꼭 필요한 어노테이션은 (     @Id     )이다.
3. Spring Data JPA는 (    JpaRepository   )를 기반으로 더욱 쉽게 데이터베이스를 사용할 수 있는 아키텍처를 제공한다.
4. DB에 접근하기 위한 로직을 관리하는 객체는 (    DAO   )이다.
5. DAO 클래스는 일반적으로 (   인터페이스   ) - (   구현체   ) 구성으로 생성한다.
6. JPA는 값을 갱신할 때 update 키워드를 사용하지 않고 (  영속성 컨텍스트   ) 를 활용한다.
7. (   롬복   )은 데이터(모델) 클래스를 생성할 때 반복적으로 사용하는 메서드를 어노테이션으로 대체하는 기능을 제공하는 라이브러리이다.

 

 

 

PROGRAMMING QUIZ

1. 다음은 Product 엔티티 클래스이다. 빈칸에 들어갈 알맞은 코드를 작성하시오.

import lombok.Getter;
import lombok.Setter;
import jakarta.persistence.*;
import java.time.LocalDateTime;

// 빈칸 1)
@Table(name="product")
@Getter
@Setter
public class Product {

    // 빈칸 2)
    // 빈칸 3) 
    private Long number;
    
    // 빈칸 4) 
    private String name;

    // 빈칸 4) 
    private Integer price;

    // 빈칸 4) 
    private Integer stock;

    private LocalDateTime createAt;

    private LocalDateTime updateAt;
    
    ... getter/setter 메서드 생략 ...
}

 

 

2. ProductDAO 인터페이스의 구현체 클래스의 일부인 상품생성 메서드 insertProduct()를 구현해라

@Override
    public Product insertProduct(Product product) {  // Product 엔티티를 DB에 저장
        Product savedProduct = // productRepository 사용
        return savedProduct;
}

 

 

 

 

 

 

 

 

 

PROGRAMMING Answer

1.

import lombok.Getter;
import lombok.Setter;
import jakarta.persistence.*;
import java.time.LocalDateTime;

@Entity  // 1
@Table(name="product")
@Getter
@Setter
public class Product {

    @Id   // 2
    @GeneratedValue(strategy = GenerationType.IDENTITY)  // 3
    private Long number;

    @Column(nullable = false)  // 4
    private String name;

    @Column(nullable = false)  // 4
    private Integer price;

    @Column(nullable = false)  // 4
    private Integer stock;

    private LocalDateTime createAt;

    private LocalDateTime updateAt;
    
    ... getter/setter 메서드 생략 ...
}

 

 

2. 

@Override
    public Product insertProduct(Product product) {  // Product 엔티티를 DB에 저장
        Product savedProduct = productRepository.save(product);

        return savedProduct;
}

[출처] 장정우, 『스프링 부트 핵심 가이드』, 위키북스(2022), p.104-158.

 

 

Corner Spring 1

Editor : via

728x90

관련글 더보기