Spring 입문 2주차 (4)

신성훈·2024년 5월 23일

TIL

목록 보기
23/162
post-thumbnail

오늘의 학습 키워드

  • SpringBoot의 JPA
  • Spring Data JPA
  • JPA Auditing 적용하기

SpringBoot의 JPA

  • SpringBoot 환경에서의 JPA
    -build.gradle : spring-boot-starter-data-jpa 추가
// JPA 설정
implementation 'org.springframework.boot:spring-boot-starter-data-jpa'

-application.properties : Hibernate 설정
->Hibernate가 DB에 요청하는 모든 SQL을 보기좋게 출력
-ddl-auto

  • create : 기존 테이블 삭제 후 다시 생성 (DROP + CREATE)
  • create-drop : create와 같으나 종료시점에 테이블을 DROP 함.
  • update : 변경된 부분만 반영
  • validate : Entity와 테이블이 정상 매핑되었는지만 확인
  • none: 아무것도 하지 않는다.
spring.jpa.properties.hibernate.use_sql_comments=true

-SpringBoot 환경에서는 EntityManagerFactory와 EntityManager를 자동으로 생성
->application.properties에 DB 정보를 전달해 주면 이를 토대로 EntityManagerFactory가 생성

@PersistenceContext
EntityManager em;

-> @PersistenceConext 애너테이션을 사용하면 자동으로 생성된 EntityManager를 주입받아 사용

  • Spring의 트랜잭션
    -Spring 프레임워크에서는 DB의 트랜잭션 개념을 애플리케이션에 적용할 수 있도록 트랜잭션 관리자를 제공

  • @Transactional 애너테이션을 클래스나 메서드에 추가하면 쉽게 트랜잭션 개념을 적용
    ->해당 메서드가 정상적으로 수행되면 트랜잭션을 커밋하고, 예외가 발생하면 롤백

  • 클래스에 선언한 @Transactional은 해당 클래스 내부의 모든 메서드에 트랜잭션 기능을 부여한다.
    -> save 메서드는 @Transactional 애너테이션이 추가되어있기 때문에 readOnly = true 옵션인 @Transactional을 덮어쓰게 되어 readOnly = false 옵션으로 적용
    readOnly = true 옵션
    -트랜잭션에서 데이터를 읽기만 할 때 사용
    -읽기 작업에 대한 최적화를 수행
    -해당 트랜잭션에서 데이터를 수정하려고 하면 예외가 발생하기 때문에 주의해야 함.

  • JPA를 사용하여 DB에 데이터를 저장, 수정, 삭제 하려면 트랜잭션 적용이 반드시 필요
    ->조회 작업은 단순하게 데이터를 읽기만 하기 때문에 트랜잭션 적용이 필수는 아니다.
    -조회 작업 기능만 존재하는 메서드일 경우에만 readOnly = true 옵션이 설정된@Transactional을 적용하면 좋다.

  • 트랜잭션 전파
    -@Transactional에서 트랜잭션 전파 옵션을 지정할 수 있다.
    -기본 옵션은 REQUIRED 이다.
    -> 부모 메서드에 트랜잭션이 존재하면 자식 메서드의 트랜잭션은 부모의 트랜잭션에 합류한다.

Spring Data JPA

  • JPA를 쉽게 사용할 수 있게 만들어놓은 하나의 모듈
    -> JPA를 추상화시킨 Repository 인터페이스를 제공

  • Repository 인터페이스는 Hibernate와 같은 JPA구현체를 사용해서 구현한 클래스를 통해 사용

  • JpaRepository 인터페이스를 구현하는 클래스를 자동으로 생성해준다.
    -> Spring 서버가 뜰 때 JpaRepository 인터페이스를 상속받은 인터페이스가 자동으로 스캔이 되면, 해당 인터페이스의 정보를 토대로 자동으로 SimpleJpaRepository 클래스를 생성해 주고, 이 클래스를 Spring ‘Bean’으로 등록한다.

  • 사용 방법
    -JpaRepository 등록

public interface "Repository 명" extends JpaRepository<"@Entity 클래스", "@Id  데이터 타입">{
}
  • JpaRepository<"@Entity 클래스", "@Id 의 데이터 타입">를 상속받는 interface 로 선언
    ->Spring Data JPA에 의해 자동으로 Bean 등록
    ->제네릭스의 @Entity 클래스 위치에 해당 Entity를 추가했기 때문에 해당 Repository는 B의 해당 테이블과 연결되어 CRUD 작업 처리하는 인터페이스가 된다.

  • SimpleJpaRepository의 save 메서드를 사용해 데이터를 저장할 수 있다.
    -> 파라미터로는 저장하려는 entity 객체를 넣어준다.

  • findAll
    -해당 메서드를 사용해 해당 테이블의 전체 데이터를 조회할 수 있다.

  • findById

private Memo findMemo(Long id) {
return memoRepository.findById(id).orElseThrow(() ->
new IllegalArgumentException("선택한 메모는 존재하지 않습니다.")
);
}

-SimpleJpaRepository의 findById 메서드를 확인 시 반환 타입이 Optional 임.
-> 파라미터로는 삭제하고자하는 Entity의 id 값을 넣어주면 된다.
-Optional<Entity 타입>을 반환 타입으로 받고 추가적으로 null을 체크하거나 orElseThrow를 사용하여 반환 값이 null일 경우 예외를 던지도록 처리할 수 있다.

  • update
@Transactional
public Long updateMemo(Long id, MemoRequestDto requestDto) {
// 해당 메모가 DB에 존재하는지 확인
Memo memo = findMemo(id);
// memo 내용 수정
memo.update(requestDto);
return id;
}

-SimpleJpaRepository에 update라는 메서드는 존재하지 않는다.
-영속성 컨텍스트의 변경감지를 통해 update를 진행, 변경감지가 적용되기 위해 해당 메서드에 @Transactional을 추가

  • delete
public Long deleteMemo(Long id) {
// 해당 메모가 DB에 존재하는지 확인
Memo memo = findMemo(id);
// memo 삭제
memoRepository.delete(memo);
return id;
}

-delete 메서드를 사용해 해당 Entity(데이터)를 테이블에서 삭제할 수 있다
-파라미터로는 삭제하려는 entity 객체를 넣어주면 된다.
-delete 메서드에 @Transactional이 적용되어있는 것을 확인할 수 있다.

JPA Auditing 적용하기

  • Timestamped
    -Spring Data JPA에서는 시간에 대해서 자동으로 값을 넣어주는 기능인 JPA Auditing을 제공

    • @MappedSuperclass
      -> JPA Entity 클래스들이 해당 추상 클래스를 상속할 경우 createdAt, modifiedAt 처럼 추상 클래스에 선언한 멤버변수를 컬럼으로 인식할 수 있다.

    • @EntityListeners(AuditingEntityListener.class)
      ->해당 클래스에 Auditing 기능을 포함시켜 줌

    • @CreatedDate
      ->Entity 객체가 생성되어 저장될 때 시간이 자동으로 저장
      ->최초 생성 시간이 저장되고 그 이후에는 수정되면 안되기 때문에 updatable = false 옵션을 추가

    • @LastModifiedDate
      ->조회한 Entity 객체의 값을 변경할 때 변경된 시간이 자동으로 저장
      ->처음 생성 시간이 저장된 이후 변경이 일어날 때마다 해당 변경시간으로 업데이트 된다.

    • @Temporal
      ->날짜 타입(java.util.Date, java.util.Calendar)을 매핑할 때 사용
      ->DB에는 Date(날짜), Time(시간), Timestamp(날짜와 시간)라는 세 가지 타입이 별도로 존재

      • DATE : ex) 2023-01-01
      • TIME : ex) 20:21:14
      • TIMESTAMP : ex) 2023-01-01 20:22:38.771000

** @SpringBootApplication 이 있는 class에 @EnableJpaAuditing 추가!

  • Query Methods
    -Spring Data JPA에서는 메서드 이름으로 SQL을 생성하는 Query Methods 기능을 제공한다.
    -SimpleJpaRepository 클래스가 생성될 때, JpaRepository 인터페이스의 모든 메서드를 자동으로 구현한다.

    -findAllByOrderByModifiedAtDesc
    ->테이블에서 ModifiedAt 즉, 수정 시간을 기준으로 전체 데이터를 내림차순으로 가져오는 SQL을 실행하는 메서드를 생성

    -List<Memo> findAllByUsername(String username);
    ->ByUsername 에 값을 전달해줘야하기 때문에 파라미터에 해당 값의 타입과 변수명을 선언하며,메서드의 파라미터를 통해 SQL에 필요한 값을 동적으로 받아 처리

📝오늘의 회고

쉽지 않다~~~
오늘도! 쳐지지 말고 포기하지말고 힘내서 가보자고~

profile
조급해하지 말고, 흐름을 만들고, 기록하면서 쌓아가자.

0개의 댓글