2009-07-10 4 views
2

웹 응용 프로그램에서 사용할 때 문제를 일으킬 Java DAO의 메서드에 'synchronized'키워드를 사용하고 있습니까?Java DAO에서 동기화를 사용하여 문제가 발생합니까?

여기에 표시된 것처럼 리소스 충돌을 피하기 위해 동기화 된 메서드가 필요한 멀티 스레드 독립 실행 형 응용 프로그램이 있기 때문에 물어 봅니다. 나는이 걱정 무엇

java.util.concurrent.ExecutionException: javax.persistence.PersistenceException: org.hibernate.HibernateException: Found shared references to a collection: com.replaced.orm.jpa.Entity.stuffCollection 

은 그 사람의 상당수가 시도하고 동기화 방법을 차단하고 전체 응용 프로그램을 느리게 할 응용 프로그램을 사용할 때.

저는 Spring에서 삽입 된 JPA 엔티티 관리자 팩토리를 사용하고 있습니다.이 팩토리 팩토리는 DAO에 엔티티 관리자를 제공합니다. 기술적으로 DAO 레이어를 제거하고 클래스가 엔티티 관리자 팩토리를 직접 호출하도록 할 수는 있지만 DAO가 제공하는 분리를 즐깁니다.

스레드간에 연결된 엔터티 ORM 개체를 전달하지 않도록 매우 조심하고 있습니다. 필자는 DAO에 액세스 할 때 리소스 충돌 오류가 발생한다고 추측합니다. 여러 스레드가 동시에 가고 비 지속성 방식으로 데이터베이스에서 지속하거나 읽으려고합니다.

이 경우 DAO를 사용하면 더 많은 피해를 입히고 도움이됩니까?


큰 문제는 DAO가 싱글 톤이 아니라는 것입니다. 내가 그 세부 사항을 포함 할만큼 충분히 명쾌하게 생각해왔다면 아마도 처음에는 그 질문을하지 않았을 것입니다.

올바르게 이해하면 Spring은 그것을 사용하는 각 클래스에 대해 DAO 클래스의 새 인스턴스를 만듭니다. 따라서 backing entity manager는 각 스레드마다 고유해야합니다. 엔티티 관리자를 공유하지 않는 것은 Rob H가 대답 한 것처럼 핵심적인 부분입니다.

그러나 이제 동기화를 제거 할 때 오류가 발생하는 이유를 알 수 없습니다.


thread에 따르면, @PersistenceContext 주석은 스레드 안전 SharedEntityManager을 만듭니다. 따라서 싱글 톤 DAO를 생성 할 수 있어야합니다.

+0

동기를 사용하는 이유와 관련하여 어떤 종류의 "리소스 충돌"을 확장 할 수 있습니까? – skaffman

답변

2

스레드간에 엔티티 개체를 공유하지 않는다고합니다.좋습니다. 하지만 스레드간에 EntityManager 개체 (또는 세션 개체는 최대 절전 모드로 공유하지 않음)도 함께 배포해야합니다. Spring과 같은 프레임 워크는 스레드 로컬 변수에 세션을 저장하여 자동으로이를 관리합니다. 프레임 워크의 도움없이 자신의 DAO를 코딩하는 경우 공유를 피하기 위해주의를 기울여야합니다.

일단 이렇게하면 대화 상태가 스레드간에 공유되지 않으므로 DAO 방법을 동기화 할 이유가 없어야합니다. 이는 고도의 동시 웹 응용 프로그램에 매우 중요합니다. 다른 방법은 하나의 쓰레드 만 DAO 인스턴스를 공유한다고 가정하고 한 번에 하나의 쓰레드 만 DAO에 액세스 할 수 있습니다. 처리량이 좋지 ​​않습니다.

+0

Spring이 필요로하는 클래스에 주입 된 엔티티 관리자에 대한 직접 액세스로 돌아가서 프레임 워크가 작동하도록하는 것이 더 낫다고 생각합니까? –

+1

"엔티티 관리자에 대한 직접 액세스"란 무엇을 의미하는지 확신 할 수 없습니다. 일반적으로 DAO에서만 엔티티 관리자에 액세스합니다. DAO가 JpaDaoSupport를 서브 클래스 화함으로써 스레드 로컬 엔티티 관리자에 쉽게 액세스 할 수 있습니다. (자세한 내용은 Spring 문서를 참조하십시오.) 그런 다음 Spring을 사용하여 DAO를 비즈니스 서비스 객체에 삽입합니다. 비즈니스 서비스는 EM을 직접 사용하지 않습니다. –

+0

JpaDaoSupport를 살펴 보겠습니다. 필자가 직접 액세스하는 것은 데이터베이스 액세스가 필요한 각 클래스에서 스프링이 삽입 된 엔티티 관리자를 갖는 것입니다. 주석으로 처리하는 것은 상당히 간단합니다. –

1

스레드 안전을 위해 동기화해야하는 경우에는 스레드를 그대로 두십시오. 이 경우 블로킹이 필요합니다.

  • 잠금 무시할 에 대한 경합이 없을 때 성능 때문에 명중 그대로두고, 그리고 미미로 촬영 : 차단은 웹 응용 프로그램의 경우에 필요하지 않은 경우 다음 중 하나를 수행 할 수 있습니다 계정 은 데이터베이스를 치는 데 드는 비용입니다.
  • 동기화 레이어를 독립 실행 형 응용 프로그램 케이스에 추가하여 이 기본이되는 비동기 DAO를 보호하도록 다시 설계하십시오.

개인적으로, 나는 그것을 그대로두고 리팩터링해야하는지 확인합니다. 그때까지는 조기 최적화를 수행하고 있습니다.

+0

로빈은 좋은 지적입니다. 내가 아직 가지지 못한 문제를 해결하려고 함정에 빠질 수도 있습니다. 나는 단지 내 접근 방식이 다른 사람들에게 심각하게 잘못되지 않았는지 확인하기를 원했습니다. –

관련 문제