首先,请不要关闭它作为什么NullPointerException
以及如何解决它的副本.我知道是什么NullPointerException
,我知道如何在我自己的代码中解决它,但不是当它被mysql-connector-java-5.1.36-bin.jar抛出时,我无法控制.
我们在mySQL数据库上运行公共数据库查询时遇到异常,该查询在大多数情况下都有效.我们在部署新版本后开始看到此异常,但发生它的查询在很长一段时间内没有发生变化.
以下是查询的外观(通过一些必要的简化).我用之前和之后执行的一些逻辑包围了它.实际的代码不是全部都在一个单独的方法中,但我把它放在一个块中,以便更容易理解.
Connection conn = ... // the connection is open ... for (String someID : someIDs) { SomeClass sc = null; PreparedStatement stmt = conn.prepareStatement ("SELECT A, B, C, D, E, F, G, H FROM T WHERE A = ?"); stmt.setString (1, "someID"); ResultSet res = stmt.executeQuery (); if (res.next ()) { sc = new SomeClass (); sc.setA (res.getString (1)); sc.setB (res.getString (2)); sc.setC (res.getString (3)); sc.setD (res.getString (4)); sc.setE (res.getString (5)); sc.setF (res.getInt (6)); sc.setG (res.getString (7)); sc.setH (res.getByte (8)); // the exception is thrown here } stmt.close (); conn.commit (); if (sc != null) { // do some processing that involves loading other records from the // DB using the same connection } } conn.close();
res.getByte(8)
NullPointerException
使用以下调用堆栈导致a :
com.mysql.jdbc.ResultSetImpl.checkColumnBounds(ResultSetImpl.java:763)com.mysql.jdbc.ResultSetImpl.getStringInternal(ResultSetImpl.java:5251)com.mysql.jdbc.ResultSetImpl.getString(ResultSetImpl.java:5173)com. mysql.jdbc.ResultSetImpl.getByte(ResultSetImpl.java:1650)org.apache.tomcat.dbcp.dbcp2.DelegatingResultSet.getByte(DelegatingResultSet.java:206)org.apache.tomcat.dbcp.dbcp2.DelegatingResultSet.getByte(DelegatingResultSet. Java的:206)
我搜索了相关mysql-connector版本的源代码,发现了这个(取自这里):
756 protected final void checkColumnBounds(int columnIndex) throws SQLException { 757 synchronized (checkClosed().getConnectionMutex()) { 758 if ((columnIndex < 1)) { 759 throw SQLError.createSQLException( 760 Messages.getString("ResultSet.Column_Index_out_of_range_low", 761 new Object[] { Integer.valueOf(columnIndex), Integer.valueOf(this.fields.length) }), SQLError.SQL_STATE_ILLEGAL_ARGUMENT, 762 getExceptionInterceptor()); 763 } else if ((columnIndex > this.fields.length)) { 764 throw SQLError.createSQLException( 765 Messages.getString("ResultSet.Column_Index_out_of_range_high", 766 new Object[] { Integer.valueOf(columnIndex), Integer.valueOf(this.fields.length) }), SQLError.SQL_STATE_ILLEGAL_ARGUMENT, 767 getExceptionInterceptor()); 768 } 769 770 if (this.profileSql || this.useUsageAdvisor) { 771 this.columnUsed[columnIndex - 1] = true; 772 } 773 } 774 }
如您所见,此行发生异常:
} else if ((columnIndex > this.fields.length)) {
这意味着this.fields
不知怎的null
.
我能找到的最接近的是这个问题,没有答案.
我怀疑问题不在我发布的查询中.Connection
由于我们在同一个连接上运行的其他一些语句,实例可能出现了问题.我只能说,我们在执行它并从中读取数据后立即关闭每个语句ResultSet
.
编辑(1/19/2017):
我无法在开发环境中重新创建错误.我认为可能是长时间使用相同连接时触发的一些mysql-connector错误.我限制上面的循环一次加载最多6个元素.另外,我们将mysql-connector版本升级到5.1.40.
我们仍然看到NullPointerException
s ResultSetImpl
,但这次是在不同的位置.
堆栈跟踪是:
com.mysql.jdbc.ResultSetImpl.getStringInternal(ResultSetImpl.java:5294)com.mysql.jdbc.ResultSetImpl.getString(ResultSetImpl.java:5151)org.apache.tomcat.dbcp.dbcp2.DelegatingResultSet.getString(DelegatingResultSet.java: 198)org.apache.tomcat.dbcp.dbcp2.DelegatingResultSet.getString(DelegatingResultSet.java:198)
这意味着这次由于我们的一个res.getString()
调用而抛出了异常(我不知道哪一个).
我发现源使用mysql-connector-java的5.1.40-bin.jar 这里和相关的代码是:
5292 // Handles timezone conversion and zero-date behavior 5293 5294 if (checkDateTypes && !this.connection.getNoDatetimeStringSync()) { 5295 switch (metadata.getSQLType()) {
暗示this.connection
是null.this.connection
是一个类型的实例变量MySQLConnection
,它在构造函数中被初始化,ResultSetImpl
并且在public void realClose(boolean calledExplicitly)
被调用时仅被设置为null (它被调用public void close()
,根据源中的文档,在被调用时ResultSet.close()
被调用).我们绝对不会ResultSet
在阅读之前读取所有数据.
任何想法如何进行?