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 특징
- JPA 추상화 Repository 제공
- CrudRepository, JpaRepository 인터페이스를 제공한다.
- SQL이나 EntityManager를 직접 호출하지 않아도 기본적인 CRUD 기능을 손쉽게 구현할 수 있다.
- JPA 구현체와 통합
- 일반적으로 Hibernate를 통해 자동으로 SQL이 생성된다.
- QueryMethods
- Method 이름만으로 SQL을 자동으로 생성한다.
- @Query 를 사용하여 JPQL 또는 Native Query를 정의할 수 있다.
- 복잡한 SQL을 직접 구현할 때 사용
- 트랜잭션 관리와 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> {
}
- Repository를 interface로 선언한다.
- 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에서 구현된다.
- 해석
- find : Entity에 매핑된 테이블(member)을 조회한다.
- ByName : 조건은 member 테이블의 name 필드이다.
- AndAddress : 또다른 조건은 member 테이블의 address 필드이다.
정답은 언제나 공식문서에 있다.
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 필드를 가지게 된다.
- 상속받는 것만으로 생성, 수정 시간을 자동으로 생성할 수 있다.
'DB 접근 > JPA ( Java Persistence API )' 카테고리의 다른 글
[JPA] 연관관계 Mapping (0) | 2025.01.06 |
---|---|
[JPA] 영속성 컨텍스트 (2) | 2025.01.04 |
[JPA] 페러다임 불일치 문제 [객체 관계형 데이터베이스] (1) | 2025.01.02 |