2011-03-25 1 views
2

며칠 동안이 문제로 고생하고 있으며 만족스럽지 못한 해결책을 찾을 수 없습니다. 아마도 다양한 수준의 간접 지정을 통해이 문제를 해결할 수 있지만, 내가 할 수 있어야하는 일종의 문제인 것처럼 보입니다. 내 문제가있을 수있는 몇 명의 다른 사람들을 찾았지만 그 중 아무도 정확한 답을 얻지 못하는 것 같습니다. 문제가 있거나 답변이 제공되지 않습니다.영속 참조가있는 개체를 지속 할 때 JPA와의 데이터베이스 교착 상태가 발생합니다.

이전에 Hibernate를 사용하여이 작업을 성공적으로 수행했지만 지금은 JPA로 작업 할 수 없었습니다.

사전 정보 다음 지속 확장을 사용

  • Guice 3.0 애플리케이션 (주석/W) 최대 절전 모드와 (최대 5 개와 연결) C3P0. 우리는 공급자로부터 EntityManager를 주입하고 있으며이 과정에서 EntityManager 객체가 트랜잭션 객체와 동일하게 유지되는지 확인할 수 있습니다.
  • 웹 애플리케이션의 일부로 설계된 현재의 문제점은 JUnit 및 dbUnit을 사용하는 자동화 된 통합 테스트에서만 발생합니다. 액세스는 싱글 톤 객체 (.in (Scopes.SINGLETON))에 대한 것이지만, 싱글 톤 객체는 인젝터에만 의존하고 @Transactional은 스레드로부터 안전합니다.
  • 데이터베이스에는 주석이 달린 FileContainer에 매핑되는 파일 테이블과 개체 MIMEType에 매핑되는 MIME 형식 테이블이 있습니다. 응용 프로그램에서 새 파일을 만들 때 먼저 MIMEType 객체를 NamedQuery로 검색하고이를 유지합니다.
  • 데이터베이스는 postgresql-8.4-702.jdbc3.jar을 사용하는 PostgreSQL 8.4입니다.
  • 시스템은 실패한 상황에 대해 적당히 까다 롭습니다. 별도의 스레드를 생성하고 거기에서 액세스를 수행해야합니다.

번째 FileContainer 객체의 마임 필드 매핑은 다음

MIME 유형 객체로 주석이
@ManyToOne(fetch=FetchType.EAGER, cascade={}) 
@JoinColumn(name="mimetype_id", referencedColumnName="id", nullable=false, updatable=true) 

다음 :

@Entity 
@Table(name="mimetypes") 
@org.hibernate.annotations.Immutable 
@Cacheable(true) 
@NamedQuery(name="mt.ext", query="from MIMEType where extension = :ext", 
    hints= {@QueryHint(name="org.hibernate.fetchSize", value="1"), 
      @QueryHint(name="org.hibernate.readOnly", value="true")}) 

위의 모든 주석은 javax.persistence 버전입니다.

addFile 방법은 @com.google.inject.persist.Transactional으로 주석됩니다. 이것을 클래스에 삽입 된 EntityManager를 사용하도록 변경하면 결과가 변경되지 않습니다.

객체를 생성하는 과정은 다음과 같이 진행됩니다

  1. 잡아 EntityManager를 인젝터에서 FileDAO. 이것들은 모두 공급자로부터 나옵니다.
  2. em.createNamedQuery ("mt.ext", MIMEType.class) .setParameter ("ext", extension)를 호출하여 데이터베이스에서 사용할 MIMEType 객체를 가져옵니다.getSingleResult();
  3. FileContainer 객체를 생성하고`setMimetype (MIME 타입)에 대한 호출을 포함하여, 그것을 채울`개체와 우리는 단지 FileContainer 객체의 기본 필드를 설정하고 em.persist(Object)를 호출
  4. 전화 dao.save(fileContainer)를 검색. 이것을 DAO에서 빼내고 EntityManager을 먼저 주사해도 결과는 바뀌지 않습니다. 삽입이 발생하고 코드 교착 상태 - 즉시 (트랜잭션의 끝에서 또는 전에 그런 일이 어디든지) EntityManager.flush()가 발생할 때이 시점에서

.

pg_stat_activity을 확인하고 pg_locks과 비교하면 insert 문이 "idle in transaction"연결에 의해 차단되고 대기 상태에 있음을 알 수 있습니다. MIMEType 삽입을 제거하고 (NULL을 허용하도록 열을 설정하면) 코드가 정상적으로 진행될 수 있으며 MIMEType의 값을 검사하면 올바르게 검색되었음을 나타냅니다.

의견이나 아이디어는 높이 평가됩니다.

EDIT :

이 계층이며, 희망이 동작들의 순서가 명확히하고 무슨된다

  • 테스트 하니스 (를 초기화 인젝터와 특정 테스트에 주입하는 러너를 사용 클래스)
    • 는 테스트 케이스는
      • 는 스레드
      • ,369 시작
      • 스레드 내에서 동일한 인젝터로 초기화 된 싱글 톤 객체에 트랜잭션 블록을 입력하면 EntityManager 객체가 모든 DAO 객체에서 동일하고 오류가 발생한 위치가 확인되었습니다.
      • EntityManager 개체는 injector.getInstance(EntityManager.class) 호출을 사용하거나 Provider 개체를 획득하여 일관되게 수집됩니다.
      • 위의 과정을 모두 같은 스레드에서 수행하십시오. 코드는 표시되지 않습니다 flush()

  • 정지는 무엇을 이해할 수있다 스레드 로컬 인젝터로 초기화되고 스레드와 모든 것을 공유되고 있어야한다 아무것도하기 나에게.

  • 답변

    2

    문제점을 발견했습니다.

    코드의 다른 부분에서 관련이 없지만 진행중인 트랜잭션이 @Before 방법으로 시작되었습니다. 웬일인지 EntityManager는 그 거래를 막고있었습니다. 이것은 모든 것이 동일한 스레드와 특정 읽기 전용 작업에있을 때 문제가 아니었지만 별도의 스레드로 분할되어 쓰기를 시도하면 다른 트랜잭션에서 대기하기 시작했습니다.이 트랜잭션은 아직 완료되지 않았습니다. 트랜잭션의 일부를 처리하고 같은 테이블을 많이 만졌습니다.

    3

    난 당신이 여기에 말한 무슨 문제가 될 가능성이 보인다에서에 따기있어 유일한 것은 이것이다 :

    시스템은 실패있는 상황에 대해 적당히 까다로운이다 : I 별도의 스레드를 생성하고 거기에서 액세스를 수행해야합니다.

    Guice-Persist 작업 단위와 트랜잭션 범위는 ThreadLocal을 사용하여 스레드로 범위가 지정됩니다. 나는 분명히 당신이 별도의 실에서 뭔가를하고 있다면 그런 일이 일어날 것을 확실히 볼 수있다. 이 개별 스레드가 언제 어떻게 사용되는지 자세히 설명해 주시겠습니까?내부에서 @Transactional 방법? 원래 스레드에 삽입 된 EntityManager을 사용하고 있습니까?

    편집 : 음 ... 나는 당신이하는 일에 어떤 문제도 보이지 않습니다. 작업과 트랜잭션이 모두 하나의 스레드에서 수행되고있는 것처럼 보입니다. 무슨 일이 일어나고 있는지 잘 모르겠다.

    +0

    물론, 상황을 명확히 할 수 있는지 알아 보겠습니다. –

    관련 문제