Spring Data JPA / JpaRepository

TopOfTheHead·2025년 11월 7일

Spring JPA

목록 보기
1/10
    

Spring Data JPA

implementation 'org.springframework.boot:spring-boot-starter-data-jpa'

JAVAORM 기술JPA를 더 간단하게 사용할 수 있도록 사용하는 Spring JPA 라이브러리
JPAEntityManager를 직접 사용하는 대신 간단하게 JpaRepository<Entity Type,Key Type>를 확장하여 활용

Spring Data JPA 내부에 Hibernate를 포함한다.

Spring Data JPA의 각 작업은 트랜잭션을 사용하지 않는 경우 DAO 작업 자체를 차단.
@Transactional을 선언하여 트랜잭션을 제어.

JPAHibernate를 사용하기 전에는 무조건 사용할 데이터베이스를 사전에 정의해야한다.

ORM 환경에서는 PK매직넘버로 찾으면 안된다.
▶ 찾은 Entity 객체가 포함하는 PK를 활용해서 찾아야함.

Spring JPA동적쿼리를 작성하지 못하는 단점이 존재
QueryDSL을 통해 개선

따로 Repository Class를 정의할 필요없이 CRUD를 수행할 DB EntityJpaRepository<Entity Type,Key Type>로 설정하여 확장하는 Repository 인터페이스를 선언 및 Service Class필드로 선언하여 CRUD 수행

public interface MemberRepository extends JpaRepository<MemberEntity, UUID> {
}
@RequiredArgsConstructor
@Service
public class MemberService {
    // 생성자 의존성 주입
	private final MemberRepository memberRepository
}

Service Class필드에 해당 인터페이스 구현체를 선언 시 Spring Context에서 자동으로 JpaRepository 구현체의존성주입하여 JpaRepository API( save() 등 )를 호출 시 Course Entity에 대한 CRUDEntity Manager에 의해 수행

Spring Data JPA 원리
Spring Data JPA는 기본적으로 EntityManger를 활용한 CRUD 메서드일반화를 통해 기본 구현하여 제공
개발자CRUD 메서드를 구현할 필요 없이 Generics타입 지정 후 해당 메서드를 사용

  • Spring Data JPA는 기본적으로 어떤 Entity 도메인에 대해서 공통적으로 일반화CRUD 메서드기본 구현하여 제공
    JpaRepositry<Entity클래스,ID타입>을 지정 시 상위 인터페이스SimpleJpaRepository -> CrudRepository ... 순으로 Entity 클래스에 대해 Generics가 설정

    Spring JPA 내 기본 구현된 CRUD 메서드들은 Generics에 지정된 Entity Class를 기반으로 작업을 수행
@Override
	@Transactional
	public <S extends T> S save(S entity) {
		Assert.notNull(entity, ENTITY_MUST_NOT_BE_NULL);
		if (entityInformation.isNew(entity)) {
			entityManager.persist(entity);
			return entity;
		} else {
			return entityManager.merge(entity);
		}
	}

SimpleJpaRepository 내 구현된 save() 메서드로서 JpaRepository<Entity클래스,ID타입>를 지정 시 해당 Entity클래스Generic이 지정.

  • JpaRepository<Entity클래스,ID타입>확장Repository 인터페이스의존성 주입Entity 클래스Generics가 지정된 SimpleJpaRepository 구현체가 주입

    。따로 Repository 인터페이스 구현체를 설계하지 않아도, 자동으로 해당 Entity 클래스Generics가 지정된 SimpleJpaRepository 구현체Repository 인터페이스Spring Bean으로 등록
    ▶ 해당 Spring Bean의존성 주입 받은 후 Spring Data JPA에서 기본 구현된 Crud 메서드를 사용

Spring Data JPA 관련 환경설정

spring:
  jpa:
    hibernate:
      ddl-auto: update
    properties:
      hibernate:
        format_sql: true
        dialect: org.hibernate.dialect.MySQLDialect
        jdbc:
          time_zone: Asia/Seoul
    show_sql: true

application.ymlspring: jpa에서 설정하는 내용

Spring Bootapplication.yml에서 spring.datasource의 설정을 수행하는 경우, 해당 설정값을 기반으로 DataSource 객체가 생성되어 Spring Bean으로 등록
DataSource 구현체의 경우 Hikari Connection Pool을 기반으로 생성됨.

   datasource:
    url: jdbc:h2:mem:test-db;MODE=MYSQL;
    username: sa
    password:
    driver-class-name: org.h2.Driver


application.ymlDataSource 설정을 기반으로 HikariCP가 생성되어 Spring Bean으로 등록

  • spring: jpa: hibernate: ddl-auto
    Spring Boot 기동 시점에서 JPA에 의한 DB Schema에 대한 처리방법을 결정하는 옵션

    ddl-auto 설정 시 hibernate에 의해 DB Entity를 기준으로 DB매핑Table이 생성

    실무에서는 보수적으로 ddl-auto를 설정
    운영서버에서는 ddl-auto: none / validate를 사용
    개발서버ddl-auto: none / validate / update, 로컬서버는 상관없이 사용

    ddl-auto: create : 기존 DB Table을 전부 DROPDB Entity 기반으로 새롭게 생성
    개발 / 테스트 환경에서 초기화 시 유용

    ddl-auto: create-drop : create와 동일하나 어플리케이션 종료 시점에서 모든 DB TableDrop
    ▶ 모든 데이터가 삭제되는 위험성이 존재하므로 테스트 환경에서만 사용

    ddl-auto: update : DB Table SchemeDB Entity 구조간 차이가 존재하는지 검사 후 DB Table업데이트
    ▶ 단 Entity가 삭제되더라도 DB Table 또는 ColumnDrop은 수행하지 않는다.
    ▶ 주로 개발 / 로컬환경에서 사용

    ddl-auto: validate : DB Table SchemeEntity 클래스 구조 간 서로 일치하는지 검사만 수행
    ▶ 불일치하는 경우 예외를 발생하여 어플리케이션이 구동되지 않도록 설정

    ddl-auto: none : hibernate를 적용하지 않도록 설정하여, 아무런 작업도 수행하지 않는다.
    ▶ 주로 운영환경에서 validate와 함께 사용

  • spring: jpa: properties: hibernate: format_sql: true
    Hibernate가 생성 및 실행하는 SQL Query콘솔에 출력 시 가독성이 좋도록 들여쓰기 / 줄바꿈하여 포맷팅.

  • spring: jpa: properties: hibernate: dialect: org.hibernate.dialect.MySQLDialect
    JPA 또는 Hibernate에서 사용하는 특정 DB에 해당하는 SQL문법기능을 사용하도록 설정

    。 각 DB는 통일된 ANSI SQL를 사용하나 각각 작은 차이가 존재하므로 보완할 필요가 존재
    Hibernate는 해당 문법/기능적 차이를 Dialect를 통해 자동으로 조정

  • spring: jpa: properties: hibernate: jdbc: time_zone
    DB Entity저장 시 시간을 통일하기위해 지역을 설정
    time_zone: Asia/Seoul

  • spring: jpa: show_sql: true
    jpa가 생성 및 실행하는 SQL Query콘솔에 출력

JpaRepository<Entity class, PK field Type> :
Spring Data JPA에서 제공하는 설정된 Entity에 대한 CRUD 기능을 제공하는 인터페이스
영속성 컨텍스트에 등록된 DB Entity에 대해 Entity Manager에 의해 자동으로 Query를 수행하는 API ( save() 등 )를 제공.

Repository 인터페이스 구현체Entity 클래스Generics로 지정된 JpaRepository<> 인터페이스SimpleJpaRepository 구현체Spring Bean으로 등록되어 의존성 주입
Entity 클래스Generics로 지정된 해당 SimpleJpaRepository에 기본 구현된 CRUD API를 사용가능

。 기존 Spring JDBCJdbcTemplate 객체의 경우 직접 SQL을 작성하여 CRUD하는 방식에 비해 매우 간편하게 사용가능

Spring Data CRUD API 메서드
Spring Data JPA는 기본적으로 EntityManger를 활용한 CRUD 메서드일반화를 통해 기본 구현하여 제공
개발자CRUD 메서드를 구현할 필요 없이 JpaRepository<>GenericsEntity Class타입 지정SimpleJpaRepository의존성 주입 받아 해당 메서드를 사용

Paging 기능을 기본으로 제공

。각 API는 용도에 맞는 SQL들이 내장되어 호출만해도 동적으로 요소가 자동으로 변경되어 적용

  • 구현체.flush() :
    commit 시 호출되어 영속성 컨텍스트 내 기존 Pending 상태인 모든 Entity매핑DB Table에 일괄적으로 반영하도록 DBSQL을 전송하는 역할을 수행
    Pending : DB Entity 변경내용이 DB에 반영되지않고 영속성 컨텍스트에만 반영된 상태

  • 구현체.saveAndFlush(DBEntity객체)
    Pending 상태의 특정 Entity만 선택하여 매핑DB Table에 반영하는 Update SQL을 전송
    EntityManager.persist()를 수행 후 flush()를 수행하는 로직을 포함
@Override
	@Transactional
	public <S extends T> S saveAndFlush(S entity) {
		S result = save(entity);
		flush();
		return result;
	}
  • 구현체.save(DBEntity객체) :
    영속성 컨텍스트EntityManager객체.persist()에 의해 DB Entity 객체INSERT하는 역할을 수행하는 API
    ▶ 이후 flush()를 통해 DB Table에 반영

    。동일한 식별자를 가진 DB Entitysave()하는 경우 UPDATE로 수행
    ▶ 기존 DB EntityUPDATE , 새로운 DB EntityINSERT

  • 구현체.delete(DBEntity객체)
    영속성 컨텍스트의 해당 DB EntitySoft Delete 수행
    영속성 컨텍스트 내에서 해당 DB Entity삭제 예정으로 등록

  • 구현체.deleteById(Id)
    영속성 컨텍스트의 해당 DB EntityHard Delete 수행

  • 구현체.findById(Id)
    SELECT 역할 수행

    JpaRepositoryfindById() 사용 시 NPE를 방지하기위해 영속성 컨텍스트에서 조회한 EntityOptional<Entity타입>으로 반환
Optional<User> user = userRepository.findById(id);
User user1 = userRepository.findById(id).get();

JpaRepository는 DB의 Id로 검색하는 findById()는 기본적으로 제공하지만, Field명으로 검색하는 기능은 구현이 되지 않았으므로, 해당 기능의 Custom Method를 구현

  • 구현체.count() :
    。특정 DB TableDB Entity의 갯수 확인

  • 구현체.findAll() :
    @Entity를 통해 특정 DB Entity ClassMappingDB Table의 모든 DB EntityList<Entity객체>으로 return
@GetMapping(path="/jpa/users")
    public List<User> ListAllUsers(){
        List<User> users = userRepository.findAll();
        return users;
    }
  • 구현체.getReferenceById() :
    DB Table에서 ID에 해당하는 Spring Bean을 return.
 
profile
공부기록 블로그

0개의 댓글