Programming/Spring

Spring Data JPA

Boxya 2025. 5. 22. 22:44

[KT] AIVLE SCHOOL 37일차

 

Spring Data 

  • 기본 데이터 저장소(DB)에 대한 특성은 유지하며, 데이터 액세스 방법에 대하여 친숙하고 익숙한 접근 방법을 제시하는 목적을 가진 Spring 기반 프로그래밍 모델
  • 데이터 액세스, 관계형 및 비관계형 데이터베이스, 클라우드 기반 데이터 서비스를 쉽게 사용할 수 있도록 함
  • 어떤 데이터 저장소(RDBMS)를 사용하더라도 일관적인 방법의 프로그래밍으로 데이터에 접근할 수 있도록 함

Spring Data JPA

  • JPA 기반 저장소를 쉽게 구현할 수 있도록 해주며, 데이터 액세스 기술을 사용하는 스프링 기반 어플리케이션을 쉽게 구축할 수 있음
  • Spring Framework 에서 제공하는 모듈 중 하나로, 개발자가 더 쉽고 편하게 JPA를 사용할 수 있도록 해줌
  • 이는 JPA를 한 단계 추상화 시킨 Repository라는 인터페이스를 제공함으로써 이루어지며, 이 때 Repository를 내부적으로 구현하는 부분에서 JPA가 사용됨
  • DDL(Data-Definition Language)
    • 데이터 정의 언어로 데이터베이스의 구조를 정의하고 관리하는 데 사용되는 SQL 명령어
    • ddl-auto는 JPA에서 사용되는 설정 중 하나로, Hibernate를 포함한 JPA 구현체가 데이터베이스의 스키마를 어떻게 처리할 지를 지정
    • DDL-auto 속성의 종류
      • create : 엔티티로 등록된 클래스와 매핑되는 테이블을 자동으로 생성
        • 이 과정에서 기존에 해당 클래스와 매핑되는 테이블이 존재한다면 기존 테이블을 삭제하고 테이블을 생성
      • create-drop : create와 동일하며 어플리케이션 종료 시 생성한 테이블을 자동으로 drop
      • update : 매핑된 테이블이 없다면 자동으로 생성하며 테이블과 엔티티의 구조가 달느 경우 엔티티 기준으로 변경
      • validate : 매핑되는 테이블들의 존재 유무만 확인
      • none(default) : 아무 작업도 수행하지 않음
  • 엔티티 매핑
    • JPA를 이용하여 데이터베이스의 테이블과 상호작용 (CRUD) 하기 위해 가장 먼저 해야 할 작업은 DB Table Entity Class 간의 매핑 작업
    • 엔티티 클래스를 생성하면 데이터베이스 테이블 구조가 자동으로 만들어짐
    • application.yml의 ddl-auto 설정에 따라 테이블 생성이 결정

Lombok 라이브러리에서 제공하는 어노테이션

  • @NoArgsConstructor : 매개변수가 없는 기본 생성자를 생성
  • JPA는 DB 값을 자바 객체로 직렬화할 때 Reflection을 이용
    • Reflection이란 구체적인 클래스 타입을 알지 못해도 그 클래스의 메소드, 타입, 변수들에 접근할 수 있도록 해주는 Java API
    • JPA에서는 자바 객체로 직렬화할 때 기본생성자를 통해 먼저 객체를 만들고나서, Reflection을 통해 필드 값을 주입
    • 따라서 Entity에는 기본생성자가 필요하고 기본생성자가 없다면 예외가 발생(InstantiationException)
  • @AllArgsConstructor : 모든 필드 값을 매개변수로 받는 생성자를 생성
  • @Getter / @Setter : 자동으로 getter , setter 메소드를 생성
  • 필드에 사용 시 해당 필드에 대한 메소드만을 만들며, 클래스에 사용시 모든 필드에 메소드를 생성
  • Lombok 어노테이션을 통해 위와 같은 코드들을 어노테이션 한 줄로 구현할 수 있어 편리
  • @Entity
    • 영속성 컨텍스트는 엔티티를 식별자 값으로 구분하므로 영속 상태로 만들려면 식별자 값이 있어야 함
    • 해당 클래스를 데이터베이스 테이블과 매핑한다고 JPA에게 알려줌
    • @Entity 어노테이션이 사용된 클래스를 엔티티(Entity) 클래스 라고 함
  • @Table
    • 엔티티 클래스를 데이터베이스의 특정 테이블에 매핑할 때 사용
    • 테이블 이름이나 카탈로그, 스키마, 유니크 제약 조건 등을 명시적으로 정의할 수 있음
    • 생략도 가능하며 사용하지 않을 시 기본적으로 클래스 이름을 테이블 이름으로 사용
  • @id
    • PK(Primary Key) 설정을 위한 어노테이션 (식별자 필드라 함)
    • 엔티티의 newsId 필드를 테이블의 ID 기본 키 컬럼에 매핑하게 됨
    • @GeneratedValue 어노테이션도 함께 사용
    • 하나의 엔티티 클래스에는 하나의 @Id 지정만 가능
    • 타입은 Integer , Long , String 등 다양한 타입으로 지정이 가능 (보통은 Long 타입을 선호)
    • PK 값은 내용상 의미를 갖지 않고 중복되지 않는 값을 사용
  • @GeneratedValue
    • 기본 키 생성 전략을 지정하는 어노테이션
    • 속성으로 strategy가 있으며 이를 통해 자동 생성 전략을 지정해줄 수 있음
    • JPA가 제공하는 기본 키 생성 전략
      • 직접 할당
        • 기본 키를 애플리케이션에서 직접 할당
        • 개발자가 직접 식별자를 할당하면 @Id 어노테이션만 있으면 됨
      • 자동 생성
        • 대리 키 사용 방식
        • GenerationType.IDENTITY ⇒ 기본 키 생성을 데이터베이스에 위임
        • 대표적 DB : MySQL , PostgreSQL , SQL Server에서 사용
    • IDENTITY 전략은 AUTO_INCREMENT처럼 DB에 값을 저장하고 나서 PK값을 구할 수 있음
      • 하지만 IDENTITY 전략을 사용하면 식별자 (기본 키)를 데이터베이스에 저장하기 전 까지는 알 수 없음
      • 따라서 em.persist() 하는 즉시 INSERT SQL이 데이터베이스에 전달됨 (엔티티가 영속 상태가 되기 위해서는 식별자가 필수이기 때문)
        • 쓰기 지연이 동작하지 않는다.
    • GenerationType.SEQUENCE ⇒ 데이터베이스 시퀸스를 사용하여 기본 키를 할당
      • 데이터베이스 시퀸스 : 유일한 값을 순서대로 생성하는 특별한 데이터베이스 오브젝트
      • 대표적 DB : ORACLE , H2 데이터베이스
    • GenerationType.TABLE ⇒ 키 생성 테이블을 사용
      • 대표적 DB : MySQL
    • GenerationType.AUTO ⇒ 사용하는 데이터베이스에 따라 자동으로 특화 방식을 설정
      • 오라클이나 H2 데이터베이스는 Sequence , MySQL은 TABLE 방식이 기본 설정
  • @Column
    • 객체 필드를 테이블 컬럼에 매핑
    • 속성
      • name : 컬럼 이름을 명시적으로 지정
      • nullable : 컬럼의 null 값 허용 여부를 설정
      • unique : 중복 방지 컬럼 여부 설정
      • length : 문자 길이 제약 조건으로, String 타입에만 사용
  • @Enumerated
    • 자바의 enum 타입을 매핑할 때 사용
    • EnumType.ORDINAL : enum index 값을 데이터베이스에 저장
    • EnumType.STRING : enum 이름을 데이터베이스에 저장
    • EnumType.ORDINAL : enum에 정의된 순서대로 ADMIN은 0, USER는 1이 데이터베이스에 저장
      • 장점 : 데이터베이스에 저장되는 데이터의 크기가 작음
      • 단점 : 이미 저장된 enum의 순서는 변경할 수 없음
      • ORDINAL은 기본값이지만, 사용에 주의해야 함
        • ADMIN(0) , USER(1) 사이에 새로운 enum이 추가되어 ADMIN(0), NEW(1), USER(2)로 변경되었다고 가정
        • USER는 데이터베이스에 2로 저장되지만 기존 데이터베이스에 저장되어 있는 USER값은 여전히 1로 남아있음
    • EnumType.STRING: enum 이름 그대로 ADMIN은 ‘ADMIN’ , USER는 ‘USER’ 로 저장
      • 장점 : 저장된 enum의 순서가 바뀌거나 추가되어도 안전
      • 단점 : ORDINAL 방식보다 저장되는 데이터 크기가 큼
  • 기타 어노테이션
    • @Temporal : 날짜 타입(java.util.Date / java.util.Calender)을 매핑
    • @CreationTimestamp : 엔티티가 데이터베이스에 저장될 때 현재의 시간을 자동으로 기록
    • @UpdateTimestamp : 엔티티가 생성 또는 업데이트될 때 현재의 시간을 자동으로 기록
    • @Transient : 특정 필드를 데이터베이스에 매핑하지 않음
    • @Lob : 데이터베이스 BLOB, CLOB 타입을 매핑
      • 데이터베이스에서 큰 데이터를 저장하는 데 사용하는 데이터 유형

연관 관계 매핑

  • 엔티티 클래스 간의 관계를 만들어 주는 것을 연관 관계 매핑 이라고 함
  • 객체는 참조를 사용해 관계를 맺고 테이블은 외래 키를 사용해서 관계를 맺음
  • 방향 방향은 객체 관계에만 존재하고 테이블 관계는 향상 양방향
  • 다중성 
    • 다대일(N:1) / 일대다(1:N) - @ManyToOne / @OneToMany
      • 다대일 관계의 반대 방향은 항상 일대다 관계고 일대다 관계의 반대 방향은 항상 다대일 관계
      • 데이터베이스의 일(1), 다(N) 관계에서 외래 키는 항상 다쪽에 있다. 따라서 객체 양방향 관계에서 연관관계의
        주인은 항상 다(N)쪽에 있음
    • 일대일(1:1) - @OneToOne
      • 일대일 관계는 양쪽이 서로 하나의 관계만 가짐
      • 테이블 관계에서 일대다, 다대일은 항상 다(N) 쪽이 외래 키를 갖는 반면에 일대일 관계는 주 테이블이나 대상 테이블 둘 중 어느 곳이나 외래 키를 가질 수 있음
      • 전통적인 데이터베이스 개발자들은 보통 대상 테이블에 외래 키를 두는 것을 선호
        • 테이블 관계를 일대다로 변경할 때 테이블의 구조를 유지할 수 있기 때문
    • 다대다(N:M) - @ManyToMany
      • 관계형 데이터베이스는 정규화 된 테이블 2개로 다대다 관계를 표현할 수 없음
      • 테이블 설계 시 다대다 관계는 중간에 테이블을 하나 추가해서 두 개의 일대다 관계를 만들어 주는 것이 일반적인 방법
  • 연관 관계의 주인
    • 객체를 양방향 연관 관계로 만들면 주인을 정해야 함
    • 두 객체 연관관계 중 하나를 정해서 테이블의 외래키를 관리해야 하는데 이것을 연관관계의 주인이라고 함
    • 연관관계의 주인을 정한다는 것은 외래 키(FK) 관리자를 선택하는 것

  • 데이터베이스에서는 외래 키 하나로 양방향 관계를 표현할 수 있지만, 객체에서는 참조를 통해 방향성이 있는 관계를 표현
  • 양방향 연관 관계
    • 두 엔티티 간에 서로를 참조할 수 있는 관계이며 양쪽에서 서로를 참조해야 하거나 양방향으로의 접근이 필요한 경우 사용
    • 양방향 연관 관계를 매핑하기 위해서는 연관 관계의 주인을 정해야 함
    • 연관 관계의 주인은 외래 키를 가지고 있는 테이블에 매핑되는 엔티티를 의미
    • 연관관계의 주인만이 DB 연관관계와 매핑되고 외래키를 관리(등록,수정,삭제) 할 수 있음
    • 반면 주인이 아닌 쪽은 읽기만 가능
    • 주인은 mappedBy 속성을 사용하지 않음
    • 주인이 아니라면 mappedBy 속성을 사용해서 속성의 값으로 연관관계 주인을 지정
  • @JoinColumn
    • 외래키를 매핑하는 데 사용되는 어노테이션
    • name 속성을 지정하지 않으면 기본적으로 필드명 + "_" + 참조하는 테이블의 @Id 컬럼명을 사용
    • Member 테이블에는 Locker 테이블의 id를 FK(Foreign Key) - 외래키로 갖게 됨
      • Address가 연관 관계의 주인

Repository

  • Spring Data JPA에서 제공하는 인터페이스
  • JPA를 사용하여 데이터베이스를 조작하기 위한 메서드를 제공
  • 인터페이스를 생성 후, Entity 클래스와 PK의 타입 (Id 컬럼의 타입) 을 매개변수로 하는 JpaRepository를 상속 받으면 기본적인 CRUD 메서드가 자동으로 생성
  • JpaRepository
    • 상속: PagingAndSortingRepository, QueryByExampleExecutor
    • 기능: 기본적인 CRUD 메서드를 포함하며, 페이징 및 정렬, 예제에 따른 쿼리 실행도 가능
  • PagingAndSortingRepository
    • 상속: CrudRepository
    • 기능: CRUD 메소드 뿐만 아니라 페이징 및 정렬을 위한 메서드도 제공
  • CrudRepository
    • 기능: 기본적인 CRUD(Create, Read, Update, Delete) 메소드를 제공
    • 메소드: save(), findById(), existsById(), count(), deleteById(), delete(), deleteAll()
  • QueryByExampleExecutor
    • 기능: 예제(Example)를 이용한 다양한 CRUD 메서드를 제공
    • 메소드: findOne(), findAll(), count(), exists()
  • 이 구조를 통해 JpaRepository를 사용하면 기본적인 CRUD 작업 뿐만 아니라 페이징, 정렬, 예제에 따른 쿼리 실행까지 다양한 기능을 활용할 수 있음

 

'Programming > Spring' 카테고리의 다른 글

REST / REST API  (1) 2025.05.23
JPA(Java Persistence API)  (0) 2025.05.23
Spring DataBase Access  (0) 2025.05.22
MVC 디자인 패턴  (0) 2025.05.22
Spring Boot  (0) 2025.05.22