2013-11-28 4 views
7

На тех же данных иногда генерируется исключение java.sql.SQLException: ORA-01002: выборка из последовательности, но в большинстве попыток все работает нормально.java.sql.SQLException: ORA-01002: выборка из последовательности на XATransaction

Приложение для Java, работающее на Glassfish 3.1.2.2. Может кто-нибудь объяснить мне, где проблема? .

@Singleton 
@LocalBean 
@Startup 
@ConcurrencyManagement(ConcurrencyManagementType.BEAN) 
public class MarketCodesSingleton { 

    @Resource(mappedName="jdbc/sss") 
    private DataSource source; 

    private volatile static Map<Interval, String> marketCodes; 

    @PostConstruct 
    @Schedule(minute="*/10", hour="*") 
    public void fillMarketCodes() { 
     try(Connection conn = source.getConnection()) { 
      Map<Interval, String> marketCodesInt = new TreeMap<>(); 
      DaoFactory.getMarketCodesDao().fillMarketCodes(marketCodesInt, conn); 
      marketCodes = Collections.unmodifiableMap(marketCodesInt); 
      Logger.getLogger(getClass().getName()).log(Level.FINE, "MarketCodes updated"); 
     } catch (SQLException e) { 
      Logger.getLogger(getClass().getName()).log(Level.SEVERE, "fillMarketCodes exception",e); 
      throw new EJBException("fillMarketCodes exception",e); 
     } 
    } 

    public String getMarketCode(Long msisdn) { 
     Interval interval = new Interval(msisdn); 
     return marketCodes.get(interval); 
    } 

} 

DaoFactory.getMarketCodesDao() fillMarketCodes:

private static final String getMarketCodes_SQL = "CALL SERVICE_PKG.GET_MARKET_CODES(?)"; 

@Override 
public void fillMarketCodes(Map<Interval, String> intervals, Connection conn) throws SQLException {  
    try (CallableStatement cs = conn.prepareCall(getMarketCodes_SQL)) { 
     //-10 is a OracleTypes.CURSOR 
     cs.registerOutParameter(1, -10); 
     cs.execute(); 
     try (ResultSet rs = (ResultSet) cs.getObject(1)) { 
      //*******Exception throws on the rs.next() in this method******* 
      while (rs.next()) { 
       Interval interval = new Interval(rs.getLong("from_no"), rs.getLong("to_no")); 
       intervals.put(interval, rs.getString("market_code")); 
      } 
     } 
    } 
} 

Процедура:

procedure GET_MARKET_CODES(
    c_cursor OUT SYS_REFCURSOR 
) AS 
    BEGIN 
    OPEN c_cursor FOR 
     SELECT from_no, to_no, market_code 
     FROM market_codes; 
    END GET_MARKET_CODES; 

свойства соединения:

<jdbc-connection-pool 
    connection-creation-retry-interval-in-seconds="5" 
    datasource-classname="oracle.jdbc.xa.client.OracleXADataSource" 
    max-pool-size="200" 
    max-connection-usage-count="1000" 
    res-type="javax.sql.XADataSource" 
    steady-pool-size="0" 
    name="sss_pool" 
    connection-creation-retry-attempts="5"> 
     <property name="URL" value="jdbc:oracle:thin:@(DESCRIPTION =(ADDRESS_LIST =(ADDRESS = (PROTOCOL = TCP)(HOST = xxx.xxx.xxx.xxx)(PORT = xx)))(CONNECT_DATA =(SERVER = DEDICATED)(SERVICE_NAME = xx)))"></property> 
     <property name="Password" value="***"></property> 
     <property name="User" value="***"></property> 
</jdbc-connection-pool> 
+0

Не могли бы вы указать параметры подключения JDBC? – vzamanillo

+0

Параметры связи были добавлены – shurik2533

+0

Попробуйте установить KeepXAConnTillTxComplete = "true", "Заставляет пул соединений резервировать физическое соединение с базой данных и поддерживать соединение с приложением во всей обработке транзакций, то есть до завершения распределенной транзакции". Возможно, ваша проблема вызвана тем, что транзакционный контекст XA соединения изменяется во время обработки набора результатов. – vzamanillo

ответ

0

Это очень странно, но проблема была решена путем удаления аннотации @ConcurrencyManagement (ConcurrencyManagementType.BEAN)

Может ли кто-нибудь объяснить это?

1

код является неполной, так что может только Догадка:

  • курсор был закрыт, и вы пытались забрать снова
  • вы сделали выбор для обновления и привержен, а затем попытался извлечь следующую строку.
+0

, как вы можете видеть в методе fillMarketCodes, курсор не был закрыт. Исключение вызывает rs.next() в этом методе , как вы можете видеть в процедуре GET_MARKET_CODES, нет инструкции для обновления – shurik2533

+0

Я хотел бы получить определение getMarketCodes_SQL. Кроме того, я настоятельно рекомендую включить трассировку sql для сеанса. – steve

+0

private static final String getMarketCodes_SQL = "CALL SERVICE_PKG.GET_MARKET_CODES (?)"; – shurik2533

1

Установлено ли ваше соединение с автоматическим фиксацией? Вывод из фиксации или откат может привести к этому исключению.

Я также заметил, что ваш SQL не окружен началом/концом, как в Oracle docs или {}, как в этом example и Oracle Javadoc.

+0

Да, это автокоммит. Для заметки фигурных скобок спасибо – shurik2533

1

Чтобы убедиться в том, поражая исключение все строки обрабатываются

Изменить код ниже, чтобы включить счетчик я, чтобы получить обработанные строки и найти фактическое количество строк

int i=0; 
    try{ 
while (rs.next()) { 
      Interval interval = new Interval(rs.getLong("from_no"), rs.getLong("to_no")); 
      intervals.put(interval, rs.getString("market_code")); 
      i=i+1; 
     } 
} 
catch (Exception e) 
{ 
Logger.getLogger(getClass().getName()).log(Level.FINE, "the total rows processed"+ i); 
Statement stmt = null; 
String query = "select count(1) count_rows     
       from market_codes"; 
    stmt = con.createStatement(); 
    ResultSet rs1 = stmt.executeQuery(query); 
    rs1.next(); 
    String countRows = rs1.getString("count_rows"); 
    Logger.getLogger(getClass().getName()).log(Level.FINE,"Actual count of rows"+ countRows); 
} 
Смежные вопросы