【问题标题】:ResultSetImpl error when implementing HIkariCP实现 HIkariCP 时出现 ResultSetImpl 错误
【发布时间】:2016-09-18 09:43:38
【问题描述】:

我正在尝试在我的程序中实现 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 对象中借用一个连接。该连接作为变量传递到CG 对象的Generate 方法中。 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)

此错误仅在运行多个线程时发生。

我做错了什么?我是否使用了错误的连接池?我错过了什么? 任何帮助将不胜感激。

【问题讨论】:

  • 您是否在“一些代码”块中对导航表进行任何更新或插入?
  • 没有。不是现在。将来可能,但现在运行此代码时我只读取数据
  • 里面好像有没有IODE列的resultSet...是否验证了所有对1到32的SV值查询都返回IODE?
  • 如果您尝试使用标准 JDBC 连接运行此代码会很好。这个问题可能与 HikariCP 完全无关
  • 是的。当我只运行一个线程时没有错误。

标签: java mysql multithreading hikaricp


【解决方案1】:

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

【讨论】:

  • 谢谢。现在可以了。使用正确的语句存在一些问题。我搬了几件东西,现在它固定了。
【解决方案2】:

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

【讨论】:

  • 谢谢。现在可以了。使用正确的语句存在一些问题。我移动了一些东西,现在它固定了。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2020-09-10
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-06-16
  • 2017-01-02
  • 2021-06-29
相关资源
最近更新 更多