2016-09-18 3 views
0

Я пытаюсь реализовать HikariCP в своей программе. У меня есть основной класс:Ошибка ResultSetImpl при реализации HIkariCP

public class ServerMain { 
final static int nPort = 8888; 
private HikariDataSource DS = null; 

public static void main(String[] args) throws IOException { 
    new ServerMain(); 
} 

public ServerMain(){ 
    DS = dsInitiate(); 

    try { 
     ServerSocket sSocket = new ServerSocket(nPort); 
     //Loop that runs server functions 
     while(true) { 
      //Wait for a client to connect 
      Socket socket = sSocket.accept(); 
      socket.setSoTimeout(30000); 

      //Create a new custom thread to handle the connection 
      ClientThread cT = new ClientThread(socket, nPort); 
      //Start the thread! 
      new Thread(cT).start(); 
     } 
    } 
    catch(IOException ex) {ex.printStackTrace();} 
} 

private static HikariDataSource dsInitiate(){ 
    HikariConfig config = new HikariConfig(); 
    config.setMaximumPoolSize(3); 

    config.setDataSourceClassName("com.mysql.jdbc.jdbc2.optional.MysqlDataSource"); 
    config.addDataSourceProperty("databaseName", "XXX"); 
    config.addDataSourceProperty("user", "XXX"); 
    config.addDataSourceProperty("password", "XXX"); 
    config.addDataSourceProperty("useSSL", "false"); 

    HikariDataSource ds = new HikariDataSource(config); 

    return ds; 
}} 

Этого класс управляет клиентскими подключениями и открывает новый поток для каждого клиента. Внутри мой основной класса у меня есть класс ClientThread:

class ClientThread implements Runnable{ 
    public void run(){ 
     /// some code ..... 
    } 

    private byte[] getFile(LocalDateTime ldt) { 
     ldt = ldt.plusSeconds(17); // 17 leap seconds 
     ldt = ldt.minusSeconds(3*3600); // 3 hours between UTC and GPS time 
     try { 
      Connection conn = DS.getConnection(); 
      CG.Generate(ldt, conn); 
     } catch (SQLException ex) {ex.printStackTrace();} 

     ///// some code ..... 
    }} 

При вызове getFile метода в классе ClientThread, соединение заимствованный из DS объекта. Это соединение передается как переменная в метод Generate объекта CG. Объект CG является экземпляром следующего класса:

public class Corr_Gen{ 
//// some variable .... 

public void Generate(LocalDateTime LDT, Connection conn){ 
    MainDB DB = new MainDB(); 
    DB.setConn(conn); 
    DB.createSTMT();  

    for (int sn = 1; sn < 33; sn++){ 
     String Q = "SELECT IODE FROM Navigation WHERE SV = "+sn+" ORDER BY Date DESC;"; 
     ResultSet rs = DB.execQuery(Q); 
     try { 
      if (rs.next()){ 
       int tmp = rs.getInt(1); /// some code .... 
      } 
     } catch (SQLException ex) {ex.printStackTrace();} 
    } 

    DB.closeSTMT(); 
    DB.closeConn(); 
}} 

Внутри Generate метода экземпляра связи передается в MainDB класс, где создается заявление. Используя этот оператор, я пытаюсь выполнить запрос. Как вы можете видеть, я закрываю оператор и соединение после того, как я в конечном итоге его использую.

Проблема в том, что когда я пытаюсь запустить более 1 потока для класса ClientThread, я получаю сообщение об ошибке, пытаясь что-то сделать с набором результатов. это ошибка: Exception in thread "Thread-0" java.lang.NullPointerException at com.mysql.jdbc.ResultSetImpl.checkColumnBounds(ResultSetImpl.java:766) at com.mysql.jdbc.ResultSetImpl.getInt(ResultSetImpl.java:2477) at com.zaxxer.hikari.proxy.HikariResultSetProxy.getInt(HikariResultSetProxy.java) at dummyTest.Corr_Gen.Generate_v2(Corr_Gen.java:37) at Exo_Ntrip_Server.ServerMain$ClientThread.getFile(ServerMain.java:131) at Exo_Ntrip_Server.ServerMain$ClientThread.response(ServerMain.java:247) at Exo_Ntrip_Server.ServerMain$ClientThread.run(ServerMain.java:107) at java.lang.Thread.run(Thread.java:745)

Эта ошибка возникает только при запуске нескольких потоков.

Что я делаю неправильно? Я неправильно использую пул соединений? Что мне не хватает? Любая помощь будет высоко оценена.

+0

Вы делаете какие-либо обновления или вставки в таблицу навигации в блоке «некоторый код»? – MGorgon

+0

№ не сейчас. возможно, в будущем, но прямо сейчас, когда я запускаю этот код, я только читаю данные –

+0

Похоже, что в нем есть resultSet без столбца IODE ... Проверено ли, что все запросы для значений SV от 1 до 32 возвращают IODE? – MGorgon

ответ

0

NPE происходит на этой линии класса MySQL ResultSetImpl:

 } else if ((columnIndex > this.fields.length)) { 

это означает, что this.fields равно нулю при чтении из этого ResultSet. Похоже, что он закрыт где-то еще в коде.

Без кода класса MainDB будет трудно воспроизвести эту проблему. Исключение выглядит так, как оператор или набор результатов закрываются в другом потоке во время чтения из ResultSet при выполнении цикла. Вы уверены, что экземпляры соединения и оператора являются частными, членами экземпляра класса MainDB?

Однако, я предлагаю, чтобы изменить код к этому:

for (int sn = 1; sn < 33; sn++){ 
    DB.createSTMT(); // make sure that connection and statement are private only for this instance DB 
    String Q = "SELECT IODE FROM Navigation WHERE SV = "+sn+" ORDER BY Date DESC;"; 
    ResultSet rs = DB.execQuery(Q); 
    try { 
     if (rs.next()){ 
      int tmp = rs.getInt(1); /// some code .... 
     } 
    } catch (SQLException ex) {ex.printStackTrace();} 
    finally { 
     DB.closeSTMT(); //make sure that this method closes correct statement and/or connection 
    } 
} 
+0

спасибо. он работает сейчас. возникла некоторая проблема с использованием правильного утверждения. я переехал пару вещей вокруг, теперь его исправлено. –

0

Я подозреваю методы в классе MainDB. особенно execQuery, который должен возвращать новый экземпляр результата каждый раз. также Если вы можете, 1. Используйте try-with-resources везде. 2. сохранить открытие и закрытие ресурса (соединение, утверждение, набор результатов) в том же методе.

+0

спасибо. он работает сейчас. возникла некоторая проблема с использованием правильного утверждения. я переехал пару вещей вокруг, теперь его исправлено. –

Смежные вопросы