3/17 TIL - JPA, 빌더 패턴 적용

큰모래·2023년 3월 18일
0
post-custom-banner

스프링부트


JPA

  • JPA의 도입으로 개발자는 DBMS를 통해 DDL,DML 조작을 하는 것이 아닌 스프링부트의 프로젝트 내에서 코드를 통해 쿼리 조작이 가능해졌다.
  • build.gradle
    • jpa 와 내가 사용하는 mysql-driver Dependency를 추가했다.

      dependencies {
          implementation 'org.springframework.boot:spring-boot-starter-data-jpa'
          runtimeOnly 'com.mysql:mysql-connector-j'
      }
  • application.properties
    • yml로 계층구조로 만드는게 뭔가 가독성도 그렇고 확실히 편한 것 같다....

      
      # 서버포트 설정
      server.port=8060
      
      # MySQL Driver 지정
      spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
      
      # DB Source URL
      spring.datasource.url=jdbc:mysql://localhost:3306/basic1
      
      # DB username
      spring.datasource.username=root
      
      # DB password
      spring.datasource.password=
      
      # jpa 구현체가 실행한 쿼리를 콘솔창에 보여준다
      spring.jpa.show-sql=true
      
      # DB TABLE 자동 생성
      # create 설정 시 스프링부트 어플리케이션을 재시작할때마다 테이블이 초기화된다.
      spring.jpa.hibernate.ddl-auto=create
      
      # hibernate가 실행한 sql 쿼리를 보기 쉽게 포맷하여 보여준다.
      spring.jpa.properties.hibernate.format_sql=true
      
      # 영속성 컨텍스트를 HTTP 요청 처리가 완료된 후에 종료하는 기능을 비활성화하는 속성
      spring.jpa.open-in-view=false
      
      # 템플릿 캐싱 기능을 비활성화
      spring.thymeleaf.cache=false
      
      # 템플릿 파일의 위치 지정
      spring.thymeleaf.prefix= file:src/main/resources/templates/
      
      # LiveReload 기능 활성화
      spring.devtools.livereload.enabled=true
      spring.devtools.restart.enabled=true

엔티티 생성

  • @Entity
    • 객체와 테이블을 매핑한다.
  • @Id
    • 기본 키 매핑
  • @GeneratedValue : 기본 키 생성 전략
    • IDENTITY : 기본 키 생성을 DB에 위임 (AUTO INCREMENT)
    • AUTO : DB에 맞게 생성 전략 자동 생성
    • SEQUENCE : 시퀀스를 사용해서 기본 키 할당
  • LocalDateTime
    • 날짜와 시간정보를 모두 포함하는 타입

@Entity
public class Article {
    @Id  // Primary Key 지정
    @GeneratedValue(strategy = GenerationType.IDENTITY)  // AUTO INCREMENT
    private long id;
    private LocalDateTime createDateTime; // 데이터 생성 날짜
    private LocalDateTime modifyDateTime; // 데이터 수정 날짜
    private String title;
    private String body;

}

JpaRepository

  • @Repository는 생략 가능
  • JpaRepositoryEntity와 관련된 CRUD 작업을 수행할 수 있는 메서드를 제공한다.
  • JpaRepository<Article, Long>
    • 엔티티의 타입과 식별자 타입을 제네릭으로 선언한다.
@Repository
public interface ArticleRepository extends JpaRepository<Article, Long> {

}

구현체가 아닌 interface임에도 정상작동할 수 있는 이유

  • 스프링 데이터 JPA에서는 JpaRepository 를 구현한 프록시 객체를 자동 생성한다.
  • 이 때, JpaRepository를 상속받은 repository는 이를 구현체로 사용한다.
  • 따라서 repository 인터페이스를 구현할 필요 없이 인터페이스 만으로 사용할 수 있게 된다.

빌더패턴

  • 객체 생성 과정을 추상화하고, 객체 생성에 필요한 매개변수를 설정할 수 있는 방법을 제공하는 디자인 패턴
  • 엔티티 클래스를 생성할 때, 빌더 패턴을 통해 가독성과 유지보수성이 향상된다.

Article 엔티티

  • @Builder 어노테이션을 통해 해당 엔티티 객체 생성 시 빌더패턴을 적용할 수 있다.
  • Article 클래스 내부에 ArticleBuilder 라는 클래스가 자동으로 생성되고 이를 통해 객체 초기화가 가능하다.

@Entity
@Getter
@Builder
@NoArgsConstructor
@AllArgsConstructor
public class Article {
    @Id  // Primary Key 지정
    @GeneratedValue(strategy = GenerationType.IDENTITY)  // AUTO INCREMENT
    private long id;
    private LocalDateTime createDate; // 데이터 생성 날짜
    private LocalDateTime modifyDate; // 데이터 수정 날짜
    private String title;
    private String body;
}

빌더패턴으로 객체 생성

  • Article.builder()를 통해 ArticleBuilder 클래스 객체를 생성
  • 이후 객체에 대한 매개변수 설정
  • 최종적으로 .build()를 통해 객체가 생성된다.
Article article = Article
                .builder()
                .title(title)
                .body(body)
                .build();

@Builder 적용 시 생성자 만드는 것에 신경 쓸 것

@Builder를 클래스에 적용 시 클래스의 모든 필드를 인자로 받는 @AllArgsConstructor를 생성해준다.

하지만 명시적으로 @NoArgsConstructor , @AllArgsConstructor 를 적용한다면 @Builder는 생성자를 생성해주지 않는다.

jpaentity는 무조건 기본 생성자를 필수로 가져야 한다. (왜지??)

자바는 명시적으로 생성자를 안만들었을때 기본 생성자를 자동으로 추가한다. 하지만, @Builder를 적용하면 모든 필드를 받는 생성자가 생성되니, 자바가 알아서 만들어주던 기본 생성자는 만들어지지 않게된다.

따라서 @NoArgsConstructor를 통해 기본생성자를 만들어준다, 이렇게 되면 @Builder는 또 @AllArgsConstructor를 만들어주지 않으니 @AllArgsConstructor 또한 따로 만들어주어야 한다. ( 나 진짜 설명 못하네 )

결론, @Builder 적용 시 @NoArgsConstructor ,@AllArgsConstructor 추가해주자..

profile
큰모래
post-custom-banner

0개의 댓글