[Spring] EntityManager & EntityManagerFactory

gwonsang247·2023년 8월 1일
0

Java

목록 보기
6/11


EntityManaagerFactory : EntityManager를 생성.
EntityManaagerFactory를 주입 받아서 사용할 수 있다.
EntityManagerFactory에서 createEntityManager()함수를 사용해서 EntityManager를 생성할 수 있다.
EntitiyManger는 Entity를 저장 관리한다. 사용자당 하나만의 EntityManger를 사용할 수 있다.즉, 공유가 불가하다.

사용자는 직접 DB에 명령을 내리는 대신에 EntityManager를 통해 DB와 데이터를 주고받는다.
SQL을 작성하지않고, EntityManager가 제공하는 메서드를 사용한다. DB에 저장은 persist(), 조회는 find(), 삭제는 remove(), 변경은 Entity의 setter.


Entity클래스의 작성

Entity클래스란 DB테이블의 한 행(row)을 정의한 것이다.
아래 코드처럼 Entity클래스를 작성하고 @Entity애너
테이션을 붙인다. 또한 키(pk)로 사용할 속성에 @Id애너테이션을 붙인다. 아래 코드에서는 id 속성이 기본키(pk)로 지정되었다. 단, Entity클래스의 속성 순서와 DB테이블의 속성 순서가 같지는 않다.(순서보장X)


Entity클래스의 작성을 위한 애너테이션


Entity Transaction

트랜잭션(transaction)이란 데이터베이스에서 논리적 상태 변화가 있는 것을 말한다.

예를들어 웹을 통해 회원 가입 설정을 만든다고 가정하면, 회원 가비을 통해서 기본적인 id와 여러 테이블에 데이터를 동시에 insert를 한다고 하자. 그런데 최초 id가 있는 기본 정보 테이블에 insert를 완료하고 여러가지 테이블에 insert를 하는 중에 에러가 발생했다.

즉, 테이블 하나 단위로 트랜잭션(transaction)을 걸어서 기본 정보에 데이터를 이미 insert했는데, 에러가 발생해서 다른 테이블에는 insert를 하지 못햇다. 그렇다면 이는 데이틔 무결성을 유지할 수 없다.

그렇기에 모든 데이터가 제대로 insert된 후에 commit을 통해서 일괄적으로 데이터를 입력하고, 만약 에러가 발생하면 commit 대신에 rollback을 통해서 중간에 insert된 데이터를 트랜잭션 범위가 시작하기 전 상태로 돌려야한다.
그것이 트랜잭션 범위 설정이다.

commit : 작업 내용을 DB에 저장
rollback : 최근 변경사항을 취소 (마지막 커밋으로 복귀)

위 코드처럼 EntityManager를 선언하고, EntityManager의 getTransaction()메서드를 통해 트랜잭션 범위를 설정할 수 있도록 한다.

이후 User객체를 선언하고, Usera의 정보를 persist()메서드를 통해 DB에 저장한다. 여기서 트랜잭션 시작부와 종료부를 지정하여 적용 범위를 설정한다.

위 코드를 실행하면 HIBERNATE는 아래와 같은 쿼리문을 자동 생성하여 실행을 한다.

HIBERNATE : insert into user (email, in_date, name, password,up_date, id) vlaues (?, ?, ?, ?, ?)

PersistenceContext

📌 perist()와 remove()

PersistenceContext란 Entity를 저장하는 공간이다. 즉 entity들이 바로 DB로 저장되지 않고 entity를 저장하는 저장소의 역할을 한다. 영속성 컨텍스트는 논리적인 개념이며 아래와 같이 EntityManger를 통헤서 영속성 컨텍스트에 접근하게 된다. 캐시, 변경 감지, 지연 로딩, 트랜잭션 지원 등의 기능을 한다.

비영속성 상태의 entity를 EntityManager의 영속 컨텍스트에 접근하도록 한다.

persist() 메서드를 통해 컨텍스트에 접근하고, remove() 메서드로 영속성을 해제한다.

EntityManager.persist(entity);
EntityManager.remove(entity);

📌 em.flush()와 tx.commit()

persist() 메서드로 entity를 컨텍스트에 접근시키면 저장됨과 동시에 SQL 저장소 내부에 DB 저장 SQL쿼리인 INSERT문이 저장된다.
flush() 메서드가 호출되기 전까지는 DB에 접근하지 않고 flush() 메서드 호출되면 SQL저장소에 저장되어있던 SQL쿼리가 DB에 entity를 전송한다.

여기서 중요한 점은 flush()매서드는 SQL쿼리 전송 commit()은 전송한 SQL쿼리 내용을 DB에 반영한다는 것이다.

EntityManager.flush(); # sql쿼리 전송
EntityTransection.commit(); # sql쿼리 DB 반영

📌 Persistece와 캐시

실제 Entity가 저장되는 공간을 Map이라고 한다. Map은 딕셔너리 형태인 Key, Value값으로 이루어진다. entity 객체에 @id 애너테이션으로 지정된 속성을 키값으로 사용한다. 구조는 아래 그림과 같다.

사용자가 find() 매서드를 사용하여 조회를 하는 경우 persisteceContext조회를 선행하고 없는 경우에 DB에 SELECT 쿼리를 전송하여 해당 정보를 찾는다.

1개의 댓글

comment-user-thumbnail
2023년 8월 1일

잘 읽었습니다. 좋은 정보 감사드립니다.

답글 달기