2016-09-18 5 views
0

내 프로그램에서 HikariCP를 구현하려고합니다.HIkariCP 구현시 ResultSetImpl 오류

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; 
}} 

이 클래스는 클라이언트 연결을 관리하고 각 클라이언트에 대해 새 스레드를 엽니 다 나는 메인 클래스가 있습니다.

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 ..... 
    }} 

ClientThread 클래스 내에서 getFile 메소드를 호출, 연결이 DS 개체에서 차용 : 내 메인 클래스의 내부에서 나는 ClientThread 클래스가 있습니다. 이 연결은 변수로 CG 개체의 Generate 메서드로 전달됩니다. 연결 인스턴스가 문이 생성 된 MainDB 클래스로 전달되는 Generate 방법 내부

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(); 
}} 

다음 CG 개체는 다음 클래스의 인스턴스입니다. 이 문을 사용하여 쿼리를 실행하려고합니다. 당신이 볼 수 있듯이, 내가 그것을 사용하여 끝나면 진술과 연결을 닫습니다.

문제는 내가 ClientThread 클래스에 대해 1 개 이상의 스레드를 실행하려고 할 때 결과 세트로 무언가를 시도하는 동안 오류가 발생합니다. 이것은 다음 오류입니다. 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

IODE 컬럼이없는 resultSet이있는 것처럼 보입니다. 1에서 32까지의 SV 값에 대한 모든 쿼리가 IODE를 반환하는 것으로 확인 되었습니까? – MGorgon

답변

0

NPE는 MySQL의 ResultSetImpl 클래스의이 라인에서 발생

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

이 this.fields가이 ResultSet에서 읽는 동안 널 (null)을 의미한다. 그것은 코드에서 다른 곳에서 닫힌 것 같습니다.

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

감사합니다. 이제 작동합니다. 올바른 진술을 사용하는 데 몇 가지 문제가있었습니다. 나는 주변에있는 몇 가지 물건을 옮겼다. –