본문 바로가기

Java/JPA

[Java/Spring] JPA / JPA 어노테이션 / JpaRepository 인터페이스

 

* JPA ( Java Persistence API )

객체와 관계형 데이터베이스를 관리하기 위한 자바의 표준 ORM 프레임워크.

Hibernate, EclipseLink, OpenJPA 등과 같은 구현체를 사용하여 실제 작업 수행.

SQL에 의존하지 않고 데이터에 접근할 수 있으며, 객체 중심 개발 가능.

JPQL( Java Persistence Query Language ), Criteria API 지원. 

 

* Spring Data JPA

JPA를 기반으로 한 Spring 프레임워크의 라이브러리.

 

* ORM (Object-Relation Mapping) : 객체와 데이터베이스 테이블 간의 매핑.

 


 

[ JPA 어노테이션 ]

JPA에서는 entity를 사용하여 객체와 데이터베이스 테이블과의 매핑을 정의하는데 이를 위한 어노테이션.

 

@Entity

해당 클래스가 JPA의 엔티티임을 나타냄.

       데이터베이스 테이블에 매핑되어 데이터를 담는 컨테이너 역할.

 

@Table

엔티티가 매핑될 데이터베이스의 테이블 정보를 지정.

엔티티의 클래스 이름과 데이터베이스 테이블 이름이 다를 때 사용.

 

@Id

엔티티의 기본 키(PK) 필드를 지정.

 

@GenerateValue 

기본 키의 값을 자동으로 생성할 방법을 지정.

 

 - GenerationType.AUTO (기본값) 

  JPA 구현체가(Hibernate 등.. ) 특정 데이터베이스가 지원하는 기본 키 생성 전략을 자동으로 선택.

@Id
@GeneratedValue(strategy = GenerationType.AUTO)
private Long id;

 

- GenerationType.IDENTITY 

데이터베이스의 IDENTITY 컬럼을 사용하여 기본 키를 생성. ( 데이터베이스가 자동으로 생성한 ID 값을 사용. )

@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;

 

@Column

엔티티 필드를 데이터베이스 테이블의 컬럼에 매핑. (이름, null 가능 여부, 길이 등 속성 지정 가능.)

@Column(name = "username", nullable = false, length = 50)
private String username;

 

@JoinColumn

외래키(FK) 컬럼 지정. ( @ManyToOne , @OneToOne 과 함께 사용. )

 

예시 )

@Entity
@Table(name = "users")
public class User {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;


    @Column(name = "user_name", nullable = false, length = 50)
    private String username;
    
}

 

=> 해당 클래스가 entity이며 데이터 베이스의 'users' 테이블과 연결.

=> 기본키는 Long 타입의 id 로 지정.

=> 데이터베이스에서 users 테이블에 id 컬럼이 ' auto-increment' 로 설정이 되어있다면 JPA는 이 설정을를 따름. 

=> name 으로 지정한 'user_name'은 데이터베이스 컬럼명, 'username'은 필드명. (null값 허용X, 최대길이 50)

 


 

* 엔티티 간의 다양한 연관관계를 나타내는 어노테이션 *

 

@ManyToOne (다대일 N:1) 

@OneToMany (일대다 1:N)

* mappedBy 속성으로 연관관계의 주인 지정. 연관관계의 주인은 외래키를 관리(생성, 업데이트, 삭제)  

 

예시)

@Entity
public class User {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;

    @OneToMany(mappedBy = "user")
    private List<Order> orders = new ArrayList<>();
}

@Entity
public class Order {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;

    @ManyToOne
    @JoinColumn(name = "user_id")
    private User user;
}

=> 'Order' 엔티티와 'User' 엔티티 사이 양방향 관계 설정.

=> 'User' 는 여러개의 'Order' 를 가질 수 있고, 각 'Order' 는 하나의 'User' 에 속할 수 있음.

=> 외래키( 'user_id' )를 소유한 'Order' 엔티티가 주인.

=> 참조필드명은 'user', 참조컬럼명은 'user_id'

 

 

@OneToOne (일대일 1:1) 

 

예시)

@Entity
public class User {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;

    @OneToOne(mappedBy = "user")
    private UserProfile profile;
    // Getter와 Setter
}

@Entity
public class UserProfile {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;

    @OneToOne
    @JoinColumn(name = "user_id")
    private User user;
    // Getter와 Setter
}

=> 'User' 엔티티와 'UserProfile' 엔티티와 일대일 관계.

=> 외래키( 'user_id' )를 소유한 'UserProfile' 엔티티가 주인.

=> 참조필드명은 'user', 참조컬럼명은 'user_id' 

 

 

@ManyToMany (다대다 N:N)  

 

예시)

@Entity
public class Student {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;

    @ManyToMany(mappedBy = "students")
    private Set<Course> courses = new HashSet<>();
    // Getter와 Setter
}

@Entity
public class Course {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;

    @ManyToMany
    @JoinTable(
        name = "course_student",
        joinColumns = @JoinColumn(name = "course_id"),
        inverseJoinColumns = @JoinColumn(name = "student_id")
    )
    private Set<Student> students = new HashSet<>();
    // Getter와 Setter
}

=> 'Student' 엔티티는 'Course' 엔티티와 다대다 관계. ('Course' 엔티티가 주인.)

=> @JoinTable 을 사용해서 두 엔티티의 연결테이블 이름, 각 엔티티를 참조하는 외래키 컬럼 지정.

=> 'course_student' 는 'Student' 엔티티와 'Course' 엔티티의 연결 테이블 이름.

=> joinColumns는 연결테이블에서 현재 엔티티인 'Course' 의 외래키 컬럼.

=> inverseJoinColumns는 연결테이블에서 현재의 반대 엔티티인 'Student' 의 외래키 컬럼.

 


 

[ JpaRepository 인터페이스 ]

Spring Data JPA 에서 제공하는 인터페이스로, JPA 기반의 Repository구현을 지원. 

=> 기본 CRUD 연산, 페이징 및 정렬 지원

 

내가 사용하려는 repository 인터페이스를 생성하고 JpaRepository 를 상속받으면 지원메소드 사용가능.

 

import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.stereotype.Repository;

@Repository
public interface UserRepository extends JpaRepository<UserEntity, Long> {
    
    // 커스터마이징 메소드 구현 가능.
    
}

 

 

 * 기본 CRUD 연산 지원 

 - save (S entity) : 주어진 엔티티를 저장 / 업데이트.

   > 해당 entity의 id가 db에 존재하지 않거나 null인 경우 저장.

   > 해당 entity의 id가 db에 존재하고, id에 대한 entity가 있는 경우 업데이트 

 - saveAll (Iterable<S> entities) : 주어진 엔티티들의 컬렉션을 저장 /  업테이트.


 - findById (ID id) : 주어진 ID에 해당하는 엔티티를 조회. 결과는 Optional<T>로 반환.

 - findAll () : 저장된 모든 엔티티를 조회. 결과는 List<T>로 반환.

 - findAllById (Iterable<ID> ids) : 주어진 ID컬렉션에 해당하는 모든 엔티티를 조회.

 - count () : db에 저장된 엔티티의 총 개수를 반환.

*  find 함수 응용 (정렬) *

  - findBy컬럼명1OrderBy 컬럼명2Desc (Asc) : 컬럼명1에 해당하는 값들을 찾아 컬럼명2에 대해 내림차순 정렬 후 반환

  - findAllOrderBy컬럼명Desc (Asc) : 컬럼명에 해당하는 데이터들을 내림차순으로 정렬 후 반환

  - findTopBy컬럼명1OrderBy컬럼명2Desc (Asc) **

      :컬럼명2에 해당하는 데이터들을 내림차순으로 정렬 후 가장 상위에 있는 컬럼명1을 반환.

 


 - delete (T entity) : 주어진 엔티티를 삭제.

 - deleteAll (Iterable<? extends T> entities) : 주어진 엔티티들의 컬렉션을 삭제.

 - deleteAll () : 모든 엔티티를 삭제.

 - deleteById (ID id) : 주어진 ID에 해당하는 엔티티를 삭제.

 

delete vs deleteById

더보기

 

 - delete 메서드는 내부적으로 id에 대한 null체크하는 로직이 포함되어 있다.

 - deleteById 는 findById로 데이터를 조회한 후 없다면 EmptyResultDataAccessException 발생. 

=> null값에 대한 예외처리 필요.

 

 

* 페이징 및 정렬 지원

 - findAll (Pageable pageable) 

 Pageable 인터페이스를 파라미터로 받아, 페이징 처리된 결과를 Page<T> 객체로 반환.

 - findAll (Sort sort)

Sort 객체를 파라미터로 받아, 정렬 기준에 맞춰 조회된 모든 엔티티를 반환.

 


 

' T ' : repository가 관리하는 엔티티 타입.

' S ' : ' T '의 하위타입. 

' ID ' : 엔티티의 기본키(PK) 타입.

 


https://velog.io/@mingsound21/4.AboutJpaRepository

 

4. JpaRepository(공통 Interface) 적용, 분석

JpaRepository 적용, 분석

velog.io