EntityManager 대 주입.EntityManagerFactory
-
19-09-2019 - |
문제
질문이 너무 길어서 양해해 주시기 바랍니다.
우리는 웹 애플리케이션에 Spring+JPA를 사용하고 있습니다.우리 팀은 주사를 두고 논쟁 중이야 EntityManagerFactory
에서 GenericDAO
(APPFUSE에서 제공하는 라인의 Generics를 기반으로 한 DAO, 우리는 사용하지 않습니다. JpaDaosupport
어떤 이유로) 과다 주입 EntityManager
.우리는 "애플리케이션 관리 지속성"을 사용하고 있습니다.
주사를 반대하는 주장 EntityManagerFactory
너무 무거워서 필요하지 않다는 점, EntityManager
우리에게 필요한 일을 합니다.또한 Spring은 모든 웹 요청에 대해 DAO의 새 인스턴스를 생성하므로(이건 의심스럽습니다) 동일한 동시성 문제는 발생하지 않습니다. EntityManager
인스턴스는 두 개의 스레드에 의해 공유됩니다.
EFM 주입에 대한 주장은 공장에 대한 핸들을 갖는 것이 항상 좋은 것보다 좋은 습관이라는 것입니다.
어느 것이 최선의 접근 방식인지 잘 모르겠습니다. 누군가 제게 알려주실 수 있나요?
해결책
EntityManagerFactory와 EntityManager를 주입하는 것의 장단점은 모두 Spring 문서에 나와 있습니다. 여기, 제가 그 점을 개선할 수 있을지 잘 모르겠습니다.
그렇다면 귀하의 질문에는 해결해야 할 몇 가지 사항이 있습니다.
... Spring은 모든 웹 요청에 대해 새로운 DAO 인스턴스를 만듭니다 ...
이것은 정확하지 않습니다.DAO가 Spring 빈인 경우 다음을 통해 달리 구성하지 않는 한 싱글톤입니다. scope
Bean 정의의 속성.모든 요청에 대해 DAO를 인스턴스화하는 것은 미친 짓입니다.
EMF를 주입한다는 주장은 공장에 대한 손잡이를 갖는 것이 항상 좋은 실습이라는 것입니다.
이 주장은 실제로 설득력이 없습니다.일반적인 모범 사례에 따르면 개체에는 해당 작업을 수행하는 데 필요한 최소한의 협력자가 주입되어야 합니다.
다른 팁
나는 내가 마침내 모은 것을 내려 놓고있다. 섹션에서 "일반 JPA를 기반으로 DAO 구현"스프링 참조에서 :
EntityManagerFactory 인스턴스는 스레드 안전이지만 EntityManager 인스턴스는 그렇지 않습니다. 주입 된 JPA EntityManager는 JPA 사양에 의해 정의 된대로 애플리케이션 서버의 JNDI 환경에서 가져온 EntityManager처럼 동작합니다. 그것은 모든 통화를 현재 트랜잭션 엔티티 매너에 위임합니다. 그렇지 않으면 작동 당 새로 생성 된 EntityManager로 돌아가서 실제로 사용 스레드 안전을 만듭니다.
이는 JPA 사양에 따라 EntityManager 인스턴스가 스레드 안전하지 않지만 스프링을 처리하면 스레드를 안전하게 안전하게 만들 수 있습니다.
Spring을 사용하는 경우 EntityManagerFactory 대신 EntityManagers를 주입하는 것이 좋습니다.
나는 이것이 이미 잘 덮여 있다고 생각하지만 몇 가지 점을 강화하기 위해서.
DAO, 봄에 주입하면 기본적으로 싱글 톤입니다. 매번 새 인스턴스를 만들려면 스코프를 프로토 타입으로 명시 적으로 설정해야합니다.
@PersistEnceContext에 의해 주입 된 엔티티 관리자 스레드 안전합니다.
즉, 나는 멀티 스레드 애플리케이션에서 Singleton Dao에 몇 가지 문제가있었습니다. 나는 결국 DAO를 Instanced Bean으로 만들었고 그 문제를 해결했습니다. 따라서 문서가 한 가지 말을 할 수 있지만 응용 프로그램을 철저히 테스트하고 싶을 것입니다.
후속 조치 :
내 문제의 일부는 내가 사용하고 있다는 것입니다.
@PersistenceContext(unitName = "unit",
type = PersistenceContextType.EXTENDED)
PersistEnceContextType.extended를 사용하는 경우 올바르게 이해하면 트랜잭션을 수동으로 닫아야합니다. 보다 이것 자세한 내용은 스레드입니다.
다른 후속 조치 :
Instanced DAO를 사용하는 것은 매우 나쁜 생각입니다. DAO의 각 인스턴스에는 고유 한 지속성 캐시가 있으며 하나의 캐시 변경은 다른 DAO 콩에 의해 인식되지 않습니다. 나쁜 조언에 대해 죄송합니다.
DAO에 @repository 스프링 주석을 설정하고 Spring에 의해 EntityManager를 관리하고 @PersistEnceContext 주석에 의해 주입되는 것이 모든 것을 유창하게 작동시키는 가장 편리한 방법이라는 것을 알았습니다. 공유 EntityManager의 스레드 안전 및 예외 번역의 혜택을 누릴 수 있습니다. 기본적으로 공유 EntityManager는 예를 들어 관리자의 여러 DAO를 결합하면 트랜잭션을 관리합니다. 결국 당신은 당신의 daos가 빈혈이 될 것임을 알게 될 것입니다.