DB 접근/JPA ( Java Persistence API )

[JPA] Spring Data JPA

JABHACK 2025. 1. 7. 10:21

Spring Boot와 JPA

📌 Spring Boot는 JPA 설정을 자동으로 구성해 주어 JPA를 쉽게 사용할 수 있도록 도와준다. 기본적으로 필요한 EntityManagerFactory와 TransactionManager를 자동으로 설정하고 데이터베이스 관련 설정을 application.properties 파일에서 간단히 지정할 수 있게 해준다.

 

public static void main(String[] args) {
    // EntityManagerFactory 생성
    EntityManagerFactory emf = Persistence.createEntityManagerFactory("test");
    // EntityManager 생성
    EntityManager em = emf.createEntityManager();
    // Transaction 생성
    EntityTransaction transaction = em.getTransaction();

    // 트랜잭션 시작
    transaction.begin();

    try {
        // 비영속
        Tutor tutor = new Tutor(1L, "wonuk", 100);

        System.out.println("persist 전");
        // 영속
        em.persist(tutor);
        System.out.println("persist 후");

        // transaction이 commit되며 실제 SQL이 실행된다.
        transaction.commit();
    } catch (Exception e) {
        // 실패 -> 롤백
        e.printStackTrace();
        transaction.rollback();
    } finally {
        // 엔티티 매니저 연결 종료
        em.close();
    }
    
    emf.close();

}
  • 기존의 방식이다.
  • 직접 트랜잭션을 사용한다.(JPA는 기본적으로 하나의 트랜잭션 안에서 기능을 수행한다)
  • 직접 EntityManagerFactory 와 EntityManager 를 생성하여 사용한다.
  • 직접 close() 하여 연결을 종료 해야한다.

 

Spring Boot와 JPA

  • JPA는 Spring에 종속적인 것이 아니다.
  • Spring Boot 에서 JPA를 사용하기 위해서는 build.gradle에 의존성 추가가 필요하다.
    • spring-boot-starter-data-jpa
    • 필요한 JPA 설정과 Entity 관리를 자동으로 해준다.
  • 자동으로 내부에서 EntityManagerFactory 를 하나만 생성해서 관리(싱글톤)한다.
    • 자동으로 Bean으로 등록된다.
    • 직접 만들지 않아도 된다.
    • 직접 연결을 close() 하지 않아도 된다.
    • application.properties 에 설정된 DB 정보로 생성된다.
  • @PersistenceContext를 통해 자동으로 생성된 EntityManager를 주입받아 사용할 수 있다.
@Repository
public class TutorRepository {
    
    @PersistenceContext
    private EntityManager em;

    public void save(Tutor tutor) {
        em.persist(tutor);
    }

    public Tutor findById(Long id) {
        return em.find(Tutor.class, id);
    }

    public List<Tutor> findAll() {
        return em.createQuery("SELECT * FROM tutor", Tutor.class).getResultList();
    }

    public void delete(Tutor tutor) {
        em.remove(tutor);
    }
}
  • EntityManager 는 Spring Data JPA에서 관리하여 직접 관리하지 않아도된다.

 

 

Spring Data JPA

📌 Spring Data JPA는 Spring Framework에서 제공하는 모듈로 JPA를 쉽게 사용할 수 있도록 지원한다. 이를 통해 데이터베이스와 상호작용을 간편하게 구현할 수 있고 코드를 간소화할 수 있다.

 

Spring Data JPA 특징

  1. JPA 추상화 Repository 제공
    • CrudRepository, JpaRepository 인터페이스를 제공한다.
    • SQL이나 EntityManager를 직접 호출하지 않아도 기본적인 CRUD 기능을 손쉽게 구현할 수 있다.
  2. JPA 구현체와 통합
    • 일반적으로 Hibernate를 통해 자동으로 SQL이 생성된다.
  3. QueryMethods
    • Method 이름만으로 SQL을 자동으로 생성한다.
    • @Query 를 사용하여 JPQL 또는 Native Query를 정의할 수 있다.
      • 복잡한 SQL을 직접 구현할 때 사용
  4. 트랜잭션 관리와 LazyLoading
    • 트랜잭션 기능을 Spring과 통합하여 제공한다.
    • 연관된 Entity를 필요할 때 로딩하는 지연로딩 기능을 지원한다.

 

 

SimpleJpaRepository

📌 Spring Data JPA의 기본 Repository 구현체로 JpaRepository 인터페이스의 기본 메서드들을 실제로 수행하는 클래스이다. 내부적으로 EntityManager를 사용하여 JPA Entity를 DB에 CRUD 방식으로 저장하고 관리하는 기능을 제공한다.

  • Spring Data JPA는 JpaRepository 인터페이스를 구현한 클래스를 자동으로 생성한다.
    • 기본적으로 SimpleJpaRepository를 구현체로 사용한다.
public interface MemberRepository extends JpaRepository<Member, Long> {
}
  1. Repository를 interface로 선언한다.
  2. JpaRepository<"@Entity 클래스", "@Id 데이터 타입"> 상속
  • 내부동작
    • Spring이 실행되면서 JpaRepository 인터페이스를 상속받은 인터페이스가 있다면, 해당 인터페이스의 정보를 토대로 SimpleJpaRepository 를 생성하고 Bean으로 등록한다.
    • 인터페이스의 구현 클래스를 직접 만들지 않아도 JpaRepository 의 기능을 사용할 수 있다.
    • 개발자가 직접 SimpleJpaRepository를 사용하거나 참조할 필요는 없다.

  • save() : 대상 Entity를 DB 테이블에 저장한다.
  • findAll() : Entity에 해당하는 테이블의 모든 데이터를 조회한다.
  • delete() : 대상 Entity를 데이터베이스에서 삭제한다.
  • 이외에도 수많은 기능(Paging, Sorting 등)이 있다.

 

 

Query Methods

📌 Spring Data JPA에서 메서드 이름을 기반으로 데이터베이스 쿼리를 자동 생성하는 기능이다. 직접 SQL을 작성하지 않고도 복잡한 쿼리를 쉽게 수행할 수 있게된다.

  • Spring Data JPA에서 메서드 이름을 기반으로 SQL을 자동으로 생성하는 기능
  • JpaRepository는 findAll(), save()와 같은 기본적인 기능만 제공한다.
  • 실제 Application 개발에는 상황에 따라 조건에 맞는 메서드가 필요하다.
public interface MemberRepository extends JpaRepository<Member, Long> {
		// Query Methods
    Member findByNameAndAddress(String name, String address);
}
// 자동으로 생성되어 실제로 실행되는 SQL
SELECT * FROM member WHERE name = ? AND address = ?;
  • JpaRepository의 제네릭에 선언된 Entity와 매핑되는 테이블의 SQL이 생성된다.
  • 개발자가 규칙에 맞게 메서드를 선언하면 SimpleJpaRepository에서 구현된다.
  • 해석
    1. find : Entity에 매핑된 테이블(member)을 조회한다.
    2. ByName : 조건은 member 테이블의 name 필드이다.
    3. AndAddress : 또다른 조건은 member 테이블의 address 필드이다.
 

JPA Query Methods :: Spring Data JPA

By default, Spring Data JPA uses position-based parameter binding, as described in all the preceding examples. This makes query methods a little error-prone when refactoring regarding the parameter position. To solve this issue, you can use @Param annotati

docs.spring.io

정답은 언제나 공식문서에 있다.

 

 

 

JPA Auditing

📌 엔티티의 생성 및 수정 시간을 자동으로 관리해주는 기능입니다. 이를 통해 개발자는 엔티티가 언제 생성되고 수정되었는지를 자동으로 추적할 수 있다.

 

모든 클래스에 생성 시간, 수정 시간 추가

@Entity
public class User {
		@Id
		private Long id;
		private String name;
		private String address;
		// 생성 시간
		private LocalDateTime createdAt;
		// 수정 시간
		private LocalDateTime updatedAt;
}

@Entity
public class Item {
		@Id
		private Long id;
		private String name;
		private String description;
		// 생성 시간
		private LocalDateTime createdAt;
		// 수정 시간
		private LocalDateTime updatedAt;
}
  • 모든 Entity가 생성 시간, 수정 시간에 대한 연산을 수행해야 한다.
  • JPA Auditing은 이러한 불편함을 해결해준다.
    • 개발자는 반복되는 불편함을 참지 않는다.

 

JPA Auditing 적용예시

@MappedSuperclass
public class BaseEntity{
		@Column(updatable = false)
		private LocalDateTime createdAt;
		private LocalDateTime updatedAt;

		@PrePersist
		public void prePersist(){
			LocalDateTime now = LocalDateTime.now();
			created_at = now;
			updated_at = now;
		}
	
		@PreUpdate
	  public void preUpdate() {
	    updated_at = LocalDateTime.now();
	  }
}

 

순수 JPA도 Auditing을 사용할 수 있지만 Spring Data JPA에서는 더 쉽게 사용할 수 있다.

 

 

Spring Data JPA Auditing Annotation

 

 

  • 적용하기

@EnableJpaAuditing

@EnableJpaAuditing
@SpringBootApplication
public class SpringDataJpaApplication {
    public static void main(String[] args) {
        SpringApplication.run(SpringDataJpaApplication.class, args);
    }

}
  • Spring Data JPA에서 Auditing을 적용할 때 사용하는 어노테이션
  • 일반적으로 Spring Boot를 실행하는 Application 클래스 상단에 선언한다.

  • Spring Boot로 만들어진 프로젝트에 기본적으로 생성되는 Application 클래스

BaseEntity 생성

@Getter
@MappedSuperclass
@EntityListeners(AuditingEntityListener.class)
public abstract class BaseEntity {

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

    @LastModifiedDate
    @Temporal(TemporalType.TIMESTAMP)
    private LocalDateTime modifiedAt;
}
  • updatable = false 설정으로 생성 시간이 수정되지 못하게 설정한다.

BaseEntity 상속

@Entity
public class User extends BaseEntity{
    @Id
    private Long id;
    private String name;
}
  • createdAt, modifedAt 필드를 가지게 된다.
  • 상속받는 것만으로 생성, 수정 시간을 자동으로 생성할 수 있다.