2009-09-09 2 views
1

Spring JDBC DAO에서 많은 양의 데이터를 처리 중이다. DAO는 BlockingQueue (take()을 사용하여 바운드 된 객체에서 반복 연산자를 반환합니다. 검색 작업은 별도의 스레드 (ExecutorService 사용)에서 일어나고 있습니다.Spring에서 동시에 JDBC ResultSet에 액세스하기

이 스레드 내부에서 다음과 같은 동작이 나타납니다. 검색은 작동하지만 ResultSet에 대한 특정 호출로 인해 호출이 중단됩니다. 이러한 호출은

  • isClosed()
  • isLast()

하지만

  • isAfterLast() 또는
  • isBeforeFirst (이다) 또는
  • isFirst() 메서드)

은 분명히 나는 ​​마지막 요소가 반복자 hasNext (거짓 산출 차단 큐에 특별한 요소를 삽입하기 위해 (무엇인지 알 필요) . 나는 ResultSet BlockingQueue에 객체를 넣기 전에 행 번호를 찾아 냄으로써이 문제를 해결할 수 있습니다. ResultSets로 작업하기위한 스레드 안전 방법이 있습니까?

멀티 스레드 데이터 소스로 전환 (필자는 C3PO ComboPooledDataSource을 테스트했습니다.) 도움이되지 않습니다.

참고 :이 문제가 처음으로 (잘못) 나에 의해 확인되었다 here

답변

1

정확한 해결책은 결과 집합 유형을 설정하는 것입니다.의 기본값은 "TYPE_FORWARD_ONLY"이고 not supported입니다. isLast()입니다. ResultSet의 형식은 예를 들어 SQL 문자열 대신 PreparedStatementCreator을 사용하여 설정할 수 있습니다. query() 에 대한 호출 JdbcTemplate. 이러한 인스턴스는 PreparedStatementCreatorFactory을 통해 가져옵니다. 그러한 팩토리에서 결과 집합의 유형 (예 : "TYPE_SCROLL_INSENSITIVE")을 설정할 수 있습니다.

+1

흠, 애매한 ..... – skaffman

1

나는 틀림없이이 실제로 자바 독에 언급되지는 않지만 java.sql.ResultSet는, 스레드 안전하다고 생각하지 않습니다. 서로 다른 스레드에서 ResultSet 메서드를 호출하면 이러한 메서드 호출이 중단됩니다.

대신에 ResultSet의 유일한 사용자로 검색 스레드를 가져와 행을 끈 다음 BlockingQueue에 데이터 자체를 덤프하는 것이 좋습니다. 그런 다음 결과 세트의 끝을 감지하고 EOF 마커를 대기열에 두는 것이 쉽습니다.

매우 큰 결과 세트를 반복하기 위해 JDBC에서 일반적으로 선호되는 메커니즘은 데이터베이스 및 JDBC 드라이버에 크게 의존하지만 속성을 java.sql.Statement으로 사용하는 것입니다. 나는 오라클 드라이버가이 설정을 존중하지만 다른 것에 대해서는 확신하지 못한다는 것을 알고 있습니다. 드라이버가 첫 번째 행을 제공하기 전에 전체 결과 집합을 메모리로 가져와야한다고 결정하면 다음 행을 가져 오는 동안 첫 번째 행을 처리 할 수 ​​없습니다.

+0

현재 가져 오기 크기를 사용 중입니다. 블로킹 큐를 사용해야하는 데이터 소비자의 (상대적으로) 처리 속도가 느립니다. AFAIK 문제의 DAO는 현재 ResultSet의 유일한 사용자입니다. 명시 적 행 계산 방법을 사용하면 상황을 그대로두고 ResultSet 동작을 문서화 할 수 있습니다. – yawn

+0

예,하지만 DAO는 여러 스레드에서 액세스되는데, 모두 동일한 ResultSet에서 작동하고 있습니까? – skaffman

+0

아니요, ResultSet은 하나의 스레드에서만 액세스해야합니다. 나는 이것을 더 깊이 조사해야 할 것이다. – yawn

관련 문제