实现HIkariCP时ResultSetImpl错误

时间:2016-09-18 09:43:38

标签: java mysql multithreading hikaricp

我正在尝试在我的程序中实现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 .....
    }}

在ClientThread类中调用getFile方法时,会从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类中。使用此语句我正在尝试执行查询。 正如您所看到的,我在结束使用它之后关闭了语句和连接。

问题在于,当我尝试为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)

只有在运行多个线程时才会发生此错误。

我做错了什么?我使用连接池错了吗?我错过了什么? 任何帮助都将受到高度赞赏。

2 个答案:

答案 0 :(得分:0)

NPE发生在MySQL ResultSetImpl类的这一行:

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

这意味着在从此ResultSet读取时this.fields为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
    }
}

答案 1 :(得分:0)

我怀疑你的MainDB类中的方法。 特别是每次都必须返回结果的新实例的execQuery。 如果可以, 1.到处使用try-with-resources。 2.以相同的方法保持资源(连接,语句,结果集)的打开和关闭。