我正在尝试在我的程序中实现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)
只有在运行多个线程时才会发生此错误。
我做错了什么?我使用连接池错了吗?我错过了什么? 任何帮助都将受到高度赞赏。
答案 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.以相同的方法保持资源(连接,语句,结果集)的打开和关闭。