[SPRING] Spring Data JPA

야부엉·2023년 11월 7일
0

SPRING

목록 보기
1/45
post-thumbnail

1. 환경 설정

1. build.gradle

  • JPA 설정 추가
// JPA 설정
implementation 'org.springframework.boot:spring-boot-starter-data-jpa'

2. application.properties

  • Hibernate 설정
spring.jpa.hibernate.ddl-auto=update

spring.jpa.properties.hibernate.show_sql=true
spring.jpa.properties.hibernate.format_sql=true
spring.jpa.properties.hibernate.use_sql_comments=true
  • show_sql, format_sql, use_sql_comments 옵션
    - Hibernate가 DB에 요청하는 모든 SQL을 보기좋게 출력 해줍니다.
  • ddl-auto
    - create : 기존 테이블 삭제 후 재생성 (Create + drop)
    - create-drop : create와 같으나 종료 시 테이블 drop
    - update : 변경된 부분만 반영
    - validate : Entity와 table 정상 맵핑되었는지만 확인
    - none : 아무것도 하지 않는다.

3. Entity 설정

package com.sparta.memo.entity;

import com.sparta.memo.dto.MemoRequestDto;
import jakarta.persistence.*;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter;

@Entity // JPA가 관리할 수 있는 Entity 클래스 지정
@Getter
@Setter
@Table(name = "memo") // 매핑할 테이블의 이름을 지정
@NoArgsConstructor
public class Memo {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;
    @Column(name = "username", nullable = false)
    private String username;
    @Column(name = "contents", nullable = false, length = 500)
    private String contents;
}

2. SpringBoot

1. Entity Manager

  • Spring Boot는 application.properties 기반으로 Entity Manager랑 Entity Manager Factory를 자동생성을 해준다.
	@PersistenceContext
	EntityManager em;
  • 위와 같이 @PersistenceContext를 사용함으로써, 자동으로 생성된 Entity Manager를 주입받아 사용할 수 있다.

2. 트랜잭션

  • Spring 프레임워크는 트랜잭션 관리자를 제공
  • @Transactionl 어노테이션을 클래스나 메서드에 추가해서 트랜잭션을 적용한다.
  • 트랜잭션을 적용한 메서드가 호출되면, 해당 메서드 내에서 수행되는 모든 DB 연산 내용은 하나의 트랜잭션으로 작동이되고, 이 때 해당 메서드가 정상적으로 수행되면 트랜잭션을 커밋하고, 예외가 발생하면 롤백합니다.
  • 클래스에 적용한 @Transactional 은, 해당 클래스 내부의 모든 매서드에 트랜잭션 기능을 부여한다.
  • JPA를 사용하여 DB에 데이터를 저장, 수정, 삭제 하려면 트랜잭션 적용이 반드시 필요합니다.
  • 아래 코드를 보면 클래스에 readOnlty = true 설정으로 @Transactional 어노테이션을 적용시켰지만, save 메서드에 새로운 @Tranasactional 어노테이션을 덮어씀으로써 설정값을 받지 않게 된다. 즉 readOnly = false 옵션으로 적용하게 된다.

    readOnly = True 옵션

    • 트랜잭션에서 데이터를 읽기만 할 때 사용, 읽기 작업에 대한 최적화로 수행
@Transactional(readOnly = true)
public class SimpleJpaRepository<T, ID> implements JpaRepositoryImplementation<T, ID> {
						...
			
		@Transactional
		@Override
		public <S extends T> S save(S entity) {
		
			Assert.notNull(entity, "Entity must not be null");
		
			if (entityInformation.isNew(entity)) {
				em.persist(entity);
				return entity;
			} else {
				return em.merge(entity);
			}
		}

						...
}

3. 영속성 컨텍스트와 트랜잭션의 생명주기

  • 스프링 컨테이너에서 트랜잭션과 영속성 컨텍스트의 생명주기는 같기 때문에, 트랜잭션이 유지되는 동안은 영속성 컨텍스트도 계속 유지가 되고, 영속성 컨텍스트의 기능을 사용할 수 있다.

4. 트랜잭션 전파

  • @Transactional에서 트랜잭션 전파 옵션을 지정할 수 있다.
  • default로는 REQUIRED옵션

    - REQUIRED옵션은 부모 메서드에 트랜잭션이 존재하면, 자식 메서드의 트랜잭션은 부모의 트랜잭션에 합류하게 된다.
  • 코드로 확인하기
//MemoRepository 클래스
@Transactional
public Memo createMemo(EntityManager em) {
    Memo memo = em.find(Memo.class, 1);
    memo.setUsername("Robbie");
    memo.setContents("@Transactional 전파 테스트 중!");

    System.out.println("createMemo 메서드 종료");
    return memo;
}

//test 클래스
@Test
    @Transactional
    @Rollback(value = false)
    @DisplayName("트랜잭션 전파 테스트")
    void test3() {
        memoRepository.createMemo(em);
        System.out.println("테스트 test3 메서드 종료");
    }
  • 자식 메서드에 @Transactional이 있기 때문에 원래는 createMemo 메서드 종료가 된 이후에 commit이 일어나고 update SQL이 작동해야하는데 부모 메서드가 끝나니까 UpdateSQL이 작동 했다 -> 자식 메서드의 트랜잭션이 부모 트랜잭션에 합쳐졌다 -> 트랜잭션 전파가 일어났다.

3. Spring Data JPA란 무엇일까?

  • Spring Data JPA는 JPA를 쉽게 사용할 수 있게 만들어놓은 하나의 모듈이다.
    - JPA를 추상화시킨 Repository 인터페이스를 제공
  • Repository 인터페이스Hibernate와 같은 JPA구현체를 사용해서 구현한 클래스를 통해 사용됩니다.
    • 개발자들은 Repository 인터페이스를 통해 JPA를 간편하게 사용할 수 있게 되었습니다.

1. SimpleJpaRepository

  • Spring 서버가 작동이 되면, JpaRepository를 상속 받은 인터페이스가 자동으로 스캔이 되고, 해당 인터페이스의 정보를 토대로 SimpJpaRepository 클래스를 자동으로 생성한 후, 이 클래스를 Spring Been에 등록한다.
  • 따라서 인터페이스의 구현 클래스를 직접 작성하지 않아도 JpaRepository 인터페이스를 통해 JPA의 기능을 사용할 수 있습니다.

2. Spring Data JPA 사용방법

  • 위와 같이, JpaRepository<"@Entity 클래스", "@Id 의 데이터 타입">를 상속받는 interface 로 선언합니다.
  • Spring Data JPA에 의해 자동으로 been 등록이 되고, 제너릭스의 @Entity 클래스 위체에 해당 memo Entity를 추가했기 때문에 memoRepository는 DB의 Memo 테이블과 연결되었다(CRUD 작업을 처리하는 인터페이스가 되었다)

4. JPA Auditing

  • Spring Data JPA에서는 시간에 대해서 자동으로 값을 넣어주는 기능인 JPA Auditing을 제공하고 있다.
@Getter
@MappedSuperclass
@EntityListeners(AuditingEntityListener.class)
public abstract class Timestamped {

    @CreatedDate
    @Column(updatable = false)
    @Temporal(TemporalType.TIMESTAMP)
    private LocalDateTime createdAt;

    @LastModifiedDate
    @Column
    @Temporal(TemporalType.TIMESTAMP)
    private LocalDateTime modifiedAt;
}
  • @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 추가

  • JPA Auditing 기능을 사용하겠다는 정보를 전달해주기 위해 @EnableJpaAuditing 을 추가해야합니다.

5. Query Methods

  • Spring Data JPA에서는 메서드 이름으로 SQL을 생성할 수 있는 Query Methods 기능을 제공한다.
  • JpaRepository 인터페이스에서 해당 인터페이스와 매핑되어있는 테이블에 요청하고자하는 SQL을 메서드 이름을 사용하여 선언할 수 있습니다.
  • SimpleJpaRepository가 생성 될 때, 아래처럼 직접 선언한 JpaRepository 인터페이스의 모든 메서드를 자동으로 구현해준다 -> 메서드 이름 패턴으로 메서드를 선언만 하면된다.(구현 x)
  • 예시
public interface MemoRepository extends JpaRepository<Memo, Long> {
    List<Memo> findAllByOrderByModifiedAtDesc();
    List<Memo> findAllByUsername(String username);
}

출처

내일배움캠프 Spring Master강의

profile
밤낮없는개발자

0개의 댓글