[java] JPA 엔티티 관리자를 닫아야합니까?

아래 방법이 있습니다.

public Profile readUser(String email){
    EntityManager em = EMF.get().createEntityManager();
    return em.find(Profile.class, email);
}

위의 엔티티 관리자 사용이 괜찮습니까? 아니면 그들을 닫아야합니까?



답변

나는 대답은 가정 : 그것은 의존한다 .

엔터티 관리자는 엔터티가 상주하는 컨텍스트에 액세스 할 수있는 열쇠입니다. 애플리케이션이 JSE 애플리케이션 인 경우 컨텍스트의 기대 수명을 고려해야합니다.

사용자의 요청에 따라 엔티티 관리자를 생성한다고 가정 해 보겠습니다. 따라서 주어진 요청에 참석하는 동안 엔터티 관리자를 열어두고 완료하면 닫습니다.

JSE 응용 프로그램에서는 엔티티 관리자가 응용 프로그램의 전체 수명 동안 열려있는 상태로 유지하고 (대량의 데이터를 처리하지 않는 경우) 응용 프로그램이 종료 될 때 닫는다 고 생각했을 수 있습니다.

결론적으로, 언제 열거 나 닫을 때 전략과 디자인에 전적으로 의존합니다. 컨텍스트에서 엔티티가 더 이상 필요하지 않을 때 닫습니다.

귀하의 예에서는 분명하지 않지만 메소드에서 EM을 생성하기 때문에 반환하기 전에 닫아야합니다. 그렇지 않으면 더 이상 액세스 할 수 없습니다 (일부 레지스트리에 보관하지 않는 한, 코드에서 분명하지 않음).

닫지 않으면 엔티티 사용이 끝난 후에도 첨부 된 상태로 유지됩니다. EM에 더 이상 액세스 할 수없는 경우에도 컨텍스트는 유지됩니다.

JPA 사양 자세한 내용이 포함되어 있습니다. 섹션 7.7 애플리케이션 관리 지속성 컨텍스트에서 다음과 같이 말합니다.

애플리케이션 관리 엔티티 관리자를 사용하는 경우 애플리케이션은 지속성 공급자의 엔티티 관리자 팩토리와 직접 상호 작용하여 엔티티 관리자 라이프 사이클을 관리하고 지속성 컨텍스트를 획득 및 파괴합니다.

이러한 모든 애플리케이션 관리 지속성 컨텍스트는 범위가 확장되며 여러 트랜잭션에 걸쳐있을 수 있습니다.

EntityManagerFactory.createEntityManager방법 및
EntityManager closeisOpen방법은 애플리케이션 관리 엔티티 관리자의 기간 및 관련 퍼시스턴스 컨텍스트를 관리하는 데 사용된다.

확장 지속성 컨텍스트는를 EntityManagerFactory.createEntityManager통해 엔티티 관리자가 닫힐 때까지 엔티티 관리자가 작성된 지점부터 존재합니다
EntityManager.close.

애플리케이션 관리 엔티티 관리자에서 확보 한 확장 지속성 컨텍스트는 트랜잭션과 함께 전파되지 않는 독립형 지속성 컨텍스트입니다.

[…]이 EntityManager.close메서드는 지속성 컨텍스트 및 기타 리소스를 해제하기 위해 엔티티 관리자를 닫습니다. 가까운 호출 한 후 응용 프로그램은에 더 메소드 호출하지 않아야
EntityManager을 제외하고 인스턴스를 getTransaction하고 isOpen, 또는이 IllegalStateException발생합니다. 트랜잭션이 활성 상태 일 때 close 메서드가 호출되면 트랜잭션이 완료 될 때까지 지속성 컨텍스트가 관리됩니다.

EntityManager.isOpen메서드는 엔티티 관리자가 열려 있는지 여부를 나타냅니다. 이 isOpen메서드는 엔티티 관리자가 닫힐 때까지 true를 반환합니다. 이것이 어떻게 작동하는지 실제로 이해하려면 엔티티 관리자와 컨텍스트 간의 관계를 이해하는 것이 중요합니다.

따라서 엔티티 관리자는 엔티티에 액세스하는 데 사용하는 공용 인터페이스이지만 엔티티 관리자에 연결된 컨텍스트에 상주합니다. 다양한 유형의 컨텍스트의 수명주기를 이해하면 질문에 대한 답을 얻을 수 있습니다.

지속성 컨텍스트는 다른 유형일 수 있습니다. Java EE 애플리케이션에서 트랜잭션 범위 지속성 컨텍스트 또는 확장 지속성 컨텍스트를 가질 수 있습니다 . JSE 애플리케이션에서 컨텍스트의 특성은 개발자제어합니다 .

엔터티 관리자에게 엔터티를 요청하면 연결된 컨텍스트에서 엔터티를 찾고 거기에서 엔터티를 찾으면 반환하고 그렇지 않으면 데이터베이스에서 엔터티를 검색합니다. 컨텍스트에서이 항목에 대한 후속 호출은 동일한 항목을 반환합니다.

거래 범위

트랜잭션 범위 지속성 컨텍스트를 사용하는 Java EE 애플리케이션에서 엔티티 관리자에 처음 액세스 할 때 컨텍스트가 아직없는 경우 현재 JTA 트랜잭션에 컨텍스트가 첨부되어 있는지 확인하고 새 컨텍스트가 생성되고 엔티티 관리자가 링크됩니다. 이 맥락에. 그런 다음 엔터티를 데이터베이스에서 읽고 (있는 경우 캐시에서 o) 컨텍스트에 배치합니다. 트랜잭션이 종료되면 (커밋 또는 롤백) 컨텍스트가 무효화되고 그 안의 모든 항목이 분리됩니다. 이것은 Stateless 세션 Bean에 대한 고전적인 시나리오입니다.

@PersistenceContext(unitName="EmplService")
EntityManager em;

이것은 또한 트랜잭션을 디자인하는 방법에 따라 둘 이상의 컨텍스트로 끝날 수 있음을 의미합니다.

확장 지속성 컨텍스트

Stateful Session Bean이있는 Java EE 애플리케이션에서는 Bean이 제거로 표시 될 때까지 커밋하는 것을 좋아하지 않기 때문에 여러 Bean 호출에서 지속되는 컨텍스트를 선호 할 수 있습니다. 이러한 경우 확장 된 지속성 컨텍스트를 사용해야합니다. 이 경우 지속성 컨텍스트는 처음 필요할 때 생성되지만 제거 할 상태 저장 빈을 표시 할 때까지 유효하지 않습니다.

@PersistenceContext(unitName="EmplService", type=PersistenceContextType.EXTENDED)

즉, Stateful 세션 Bean 메소드의 후속 호출에서이 Bean에 삽입되는 엔티티 관리자의 인스턴스에 관계없이 항상 동일한 컨텍스트에 액세스 할 수 있으므로 후속 호출도 동일한 결과를 반환합니다. 동일한 맥락이기 때문입니다.

또한 변경 사항은 Bean이 제거 용으로 표시되거나 수동으로 플러시 할 때까지 플러시되지 않습니다.

애플리케이션 관리

언제든지 엔티티 관리자 팩토리와 엔티티 관리자를 수동으로 인스턴스화 할 수 있습니다. 이것이 일반적으로 JSE 애플리케이션에서 수행하는 작업입니다. 맞습니까?

이런 종류의 응용 프로그램의 경우 일반적으로 JTA 트랜잭션을 처리 할 컨테이너가 없습니다. 따라서 리소스 로컬 트랜잭션을 사용하고 수동으로 변경 사항을 커밋하거나 롤백해야합니다.

이러한 종류의 응용 프로그램의 경우 엔터티 관리자를 인스턴스화하면 컨텍스트가 자동으로 연결됩니다.

애플리케이션에 따라 라이프 사이클이 애플리케이션 자체의 라이프 사이클에 연결된 글로벌 엔티티 관리자를 생성하도록 결정할 수 있습니다. 이는 애플리케이션의 전체 수명 동안 단일 엔티티 관리자입니다. 이 경우 엔터티 관리자를 사용하여 컨텍스트를 만들고 삭제합니다.

또는 애플리케이션 사용자와의 대화 (예 : 트랜잭션)별로 엔티티 관리자를 만들 수 있습니다. 이 경우 범위는 사용자가 결정하지만 여전히 컨텍스트는 엔티티 관리자를 사용하여 생성 및 삭제됩니다.


답변