개발자
[JPA] Entity란?(엔티티매니저/영속성/Hibernate/spring Data) 본문
[JPA] Entity란?(엔티티매니저/영속성/Hibernate/spring Data)
GoGo개발 2023. 2. 18. 16:56Entity 란?
Entity란 DB에서 영속적으로 저장된 데이터를 자바 객체로 매핑하여 '인스턴스의 형태'로 존재하는 데이터를 말한다. 쉽게 풀어보자면 테이블에 대응하는 하나의 클래스이다.
엔티티 라는 용어는 때로는 클래스를 의미하는 경우도 있고, 클래스에 의해 생성된 인스턴스를 의미하는 경우가 있다. 엔티티 클래스와 엔티티 인스턴스 혹은 엔티티 객체라는 표현이 정확하다.
엔티티는 영속성을 가진 객체로 DB테이블에 보관할 대상이다. 즉 영속 컨텍스트에 속한 객체를 말한다.(이 개념은 아래에서 추가 설명)
Entity Manager
엔티티 매니저는 엔티티 객체들을 관리하는 역할을 한다.(관리하는 역할을 수행하는 클래스) 여기서 관리란 Life Cycle이라고 할수 있다. 엔티티 매니저는 관리하는 엔티티 객체들을 영속 컨텍스트(persistence Context)에 넣어두고, 객체들의 생사를 관리한다.
그렇다면 영속 컨텍스트 라는 것은 무엇일까?
영속 컨텍스트는 JPA가 엔티티 객체들을 모아두는 공간이다. 엔티티를 영구히 저장하는 환경이라고 볼 수 있다.
엔티티 컨텍스트와 엔티티 객체 : 엔티티는 4가지 상태가 존재한다
이름 | 상태 |
비영속(New) | 영속성 컨텍스트와 연관이 없는 상태 :Java 영역에만 존재하고, 데이터베이스와 연동된 적 없는 상태.순수한 Java 객체로 엔티티 매니저가 관리하지 않음 엔티티 매니저의 persist 메소드를 사용하여 영속 상태로 변경 em.persist(someEntity); |
영속(Managed) | 영속성 컨텍스트에서 관리 중인 상태 :DB에 저장되고, 메모리상에서도 같은 상태로 존재하는 상태.PK 값을 통해 필요한 엔티티 객체를 꺼내 사용할 수 있게 된다. |
준영속(Detached) | 영속성 컨텍스트에 저장되어 있었으나 분리된 상태 :영속 컨텍스트에서 엔티티 객체를 꺼내서 사용하는 상태. 아직 DB와 동기화가 이루어지지 않은 상태 |
삭제(Removed) | 영속성 컨텍스트에서 완전히 삭제된 상태 :DB 상에서 삭제된 상태. 객체는 영속 컨텍스트에 존재하지 않습니다. |
각 단계에 대한 상세 설명은 아래 블로그 참고
https://private-space.tistory.com/81
[JPA] EntityManager, 영속성 컨텍스트
김영한 님의 [자바 ORM 표준 JPA 프로그래밍]을 읽고 내용을 정리한 것입니다. 교보문고 링크 EntityManager와 영속성 컨텍스트 mybatis처럼 직접 SQL을 작성하거나 JPA를 활용한 개발을 할 때는 눈에 보이
private-space.tistory.com
다시 엔티티 매니저로 돌아와서,
PA를 정의한 javax.persistence 패키지 대부분이 Interface 와 enum으로 구성되어있고 JPA의 핵심인 EntityManager도 interface로 정의되어 있다. 우리가 주로 사용하는 Hibernate가 JPA를 구현한 구현체이며 Hibernate 외에 여러 ORM Framework가 존재한다.
아래 EntityMAnager interface의 실제코드 일부이다.
package javax.persistence;
import ...
public interface EntityManager {
public void persist(Object entity);
public <T> T merge(T entity);
public void remove(Object entity);
public void flush();
// more...
}
Spring Data JPA(개념 후술할 예정)를 사용하지 않는다면 EntityManager에서 제공하는 API를 사용하면 된다. 작성 예시는 다음과 같다.
@Repository
@RequiredArgsConstructor
public class OrderRepository {
private final EntityManager em;
public void save(Order order){
em.persist(order);
}
public Order findOne(Long id){
return em.find(Order.class, id);
}
public List<Order> findAll() {
return em.createQuery("select o from Order o", Order.class)
.getResultList();
}
public List<Order> findAllWithItem() {
return em.createQuery(
"select distinct o from Order o" +
" join fetch o.member m" +
" join fetch o.delivery d" +
" join fetch o.orderItems oi" +
" join fetch oi.item i", Order.class)
.getResultList();
}
}
위 OrderRepository는 Spring Data JPA가 제공하는 JpaRepository를 상속하지 않고 @Repository만 추가했다. EntityManager가 제공하는 API를 활용해 적절한 API를 만들면 된다.
이렇게 JPA(Java Persistence API)에서 제공하는 EntityManager로 데이터베이스에 접근할 수 있다. 다시말해 JPA는 자바 진영에서 ORM 기술 표준으로 Application 과 JDBC 사이에서 동작한다.
- ORM (Object Relational Mapper) : 직접 SQL을 작성하지 않고도 객체지향 방식으로 DB에 접근
- JDBC (Java Database Connectivity) : Java에서 DB에 접속할 수 있도록 하는 자바 API
우리가 주로 사용하는 Hibernate는 JPA의 대표적인 프레임워크이다.
더하여 짧게 추가하자면, 엔티티 매니저는 여러 스레드가 동시에 접근하면 동시성 문제가 발생하므로 스레드 간 공유를 하면 안된다. 예를 들어 내가 데이터를 수정하고 있는데 다른 스레드에서 해당 데이터를 미리 수정해버리면 안 된다. 따라서 엔티티 매니저는 하나를 공유하면 안 되고, 상황에 따라서 계속해서 만들어줘야한다. 그럼 이런 엔티티 매니저는 누가 만들어줄까?
바로 엔티티 매니저 팩토리(EntityManagerFactory)이다.
Hibernate 란?
계속 말하지만 JPA는 interface의 모음이며 이를 구현한 구현체로 여러 ORM framwork가 존재하는데, Hibernate를 사용한다.
Spring Data JPA
JPA의 핵심인 EntityManager와 EntityManagerFactory 라이브러리는 Entity CRUD를 처리한다. 하지만 EntityManager를 직접 작성하는 경우는 거의 없고,주로 Repository Interface만 사용한다. Repository Interface의 장점은 다음과 같다.
- EntityManager를 직접 작성하지 않아도 데이터베이스에 Entity의 CRUD 처리됨
- @Repository annotation을 추가하지 않아도 Bean 으로 자동 등록됨
여기서 말하는 Repository interface는 Spring Data JPA이다. JPA 와 Spring Data JPA 는 완전히 같은 개념이 아니다.
이쯤되면 @Repository와 Repository interface 차이가 무엇인지, JPA와 Spring Data JPA의 차이가 무엇인지 알아보자
Spring Data JPA 란 JPA 를 추상화시킨 Repository Interface를 제공하여 개발자가 JPA 를 더 편하게 사용할 수 있게 하는 모듈이다.
Spring Data JPA를 사용하지 않는다면 클래스에 @Repository를 작성하고 JPA를 적용한 다음 EntityManager의 API 를 직접 호출해야 Entity에 대한 CRUD가 처리된다.
Spring Data JPA의 Repository Interface (SimpleJpaRepository)에는 EntityManager가 포함되어 있기 때문에 직접 작성하지 않아도 내부에서 자동으로 호출된다. 또한 @Repository를 작성하지 않아도 Bean으로 등록된다. 자세한 내용은 SimpleJpaRepository 코드를 보며 알아가자.
SimpleJpaRepository
Repository Interface의 기본 구현체인 SimpleJpaRepository는 Spring Data JPA가 제공하는 가장 많은 기능을 가지고 있는 가장 밑단에 있는 클래스이다.
package org.springframework.data.jpa.repository.support;
import ...
@Repository
@Transactional(readOnly = true)
public class SimpleJpaRepository<T, ID> implements JpaRepositoryImplementation<T, ID> {
private final JpaEntityInformation<T, ?> entityInformation;
private final EntityManager em;
private final PersistenceProvider provider;
public SimpleJpaRepository(JpaEntityInformation<T, ?> entityInformation, EntityManager entityManager) {...}
@Override
public Optional<T> findById(ID id) {...}
@Override
public List<T> findAllById(Iterable<ID> ids) {...}
@Override
public long count() {...}
@Transactional
@Override
public <S extends T> S save(S entity) {...}
@Override
@Transactional
@SuppressWarnings("unchecked")
public void delete(T entity) {...}
실제로 많이 사용하는 findBy~, delete, save 등의 여러 API가 SimpleJpaRepository에 구현되어있으며 더 자세한 내용은 SimpleJpaRepository Docs 을 참고하면 된다.
Repository Interface의 기본 구현체인 SimpleJpaRepository 내부에서 EntityManager를 사용하고 있기 때문에 직접 작성할 필요가 없다. 또한 클래스 레벨에 @Repository가 추가되어있기 때문에 우리는 이것 또한 작성할 필요가 없다
추가로 트랜잭션개념에 대해서도 알아야하는데 이는 후술할 포스트에 계속하겠다.
개념을 이정도로 알았으면 JPA repository method 작성법을 알아보자
JPA repository method 작성법
public interface AccountRepository extends JpaRepository<Account, Long> {
boolean existsByUsername(String username);
Optional<Account> findById(Long id);
Optional<Account> findByUsername(String username);
Optional<Account> findByUsernameAndPassword(String username, String password);
}
Repository Interface 에 정해진 규칙대로 method 입력 시 method 에 적합한 JPQL을 생성해 처리한다.
- findByentity 속성이름 : entity 속성이름으로 검색
- findByEmailOrUserId (String email, String userId) : 여러 필드로 검색
- countByentity 속성이름 : entity 속성이름에 해당하는 결과 개수를 반환
참고 블로그
https://dev-troh.tistory.com/151
https://private-space.tistory.com/81
엔티티매니저팩토리
https://perfectacle.github.io/2018/01/14/jpa-entity-manager-factory/
엔티티 하이버네이트,springdata,트랜잭션관련
https://velog.io/@evelyn82ny/JPA-vs-Spring-Data-JPA
나중에 추가로 공부할 블로그
https://ict-nroo.tistory.com/130
[JPA] 영속성 컨텍스트와 플러시 이해하기
영속성 컨텍스트JPA를 공부할 때 가장 중요한게객체와 관계형 데이터베이스를 매핑하는 것(Object Relational Mapping) 과영속성 컨텍스트를 이해하는 것 이다. 두가지 개념은 꼭 알고 JPA를 활용하자.
ict-nroo.tistory.com
https://siyoon210.tistory.com/138
JPA의 영속성 컨텍스트와 엔티티 생명주기
[개요] JPA를 공부하는데 가장 난해한 부분인 '영속성 컨텍스트'에 대해서 알아보겠습니다. 영속성 컨텍스트에 대한 지식이 수반되어야 JPA의 동작방식을 온전히 이해할 수 있습니다. [영속성 컨
siyoon210.tistory.com
'개발자 > workflow 리팩토링 프로젝트(SpringBoot,JPA,MySQL)' 카테고리의 다른 글
[RESTful API]개념 (0) | 2023.02.22 |
---|---|
[JPA] Entiy 맵핑(연관관계/어노테이션) (0) | 2023.02.19 |
[JPA] JPA란?(ORM) (0) | 2023.02.18 |
[동기/비동기] callback 함수 (0) | 2023.02.14 |
♣[WF 프로젝트] SpringBoot JPA MySQL 연동/git hub 연동 / pull request 맛보기 (오류와의 전쟁) (0) | 2023.02.11 |