2010-08-17 26 views
2

我在寫一個Java應用程序,它通過JDBC與Apache Derby一起工作。我有在下面的代碼片斷與代碼的問題:德比INSERT SELECT空指針異常

byte md5[] = md5sum(file); 

PreparedStatement s = con.prepareStatement("INSERT INTO input_files (job_ID, hash) SELECT job_id, ? FROM job WHERE job_name = ?"); 
s.setBytes(1, md5); 
s.setString(2, jobName); 
s.executeUpdate(); 
s.close(); 

此插入到以下表:

CREATE TABLE input_files 
(
    hash char(16) for bit data, 
    job_id integer REFERENCES job, 
    PRIMARY KEY(job_id, hash) 
); 

CREATE TABLE job 
(
    job_id integer PRIMARY KEY GENERATED ALWAYS as IDENTITY, 
    job_name character varying(50) UNIQUE NOT NULL, 
    #other fields 
); 

的想法是,有一個內部整數job_id其由在內部使用數據庫,但我們希望儘可能使用可讀的字符串來引用它job_name

這一致地引發以下異常。

java.sql.SQLException: Java exception: ': java.lang.NullPointerException'. 
    at org.apache.derby.impl.jdbc.SQLExceptionFactory40.getSQLException(Unknown Source) 
    at org.apache.derby.impl.jdbc.Util.newEmbedSQLException(Unknown Source) 
    at org.apache.derby.impl.jdbc.Util.javaException(Unknown Source) 
    at org.apache.derby.impl.jdbc.TransactionResourceImpl.wrapInSQLException(UnknownSource) 
    at org.apache.derby.impl.jdbc.TransactionResourceImpl.handleException(Unknown Source) 
    at org.apache.derby.impl.jdbc.EmbedConnection.handleException(Unknown Source) 
    at org.apache.derby.impl.jdbc.ConnectionChild.handleException(Unknown Source) 
    at org.apache.derby.impl.jdbc.EmbedPreparedStatement.<init>(Unknown Source) 
    at org.apache.derby.impl.jdbc.EmbedPreparedStatement20.<init>(Unknown Source) 
    at org.apache.derby.impl.jdbc.EmbedPreparedStatement30.<init>(Unknown Source) 
    at org.apache.derby.impl.jdbc.EmbedPreparedStatement40.<init>(Unknown Source) 
    at org.apache.derby.jdbc.Driver40.newEmbedPreparedStatement(Unknown Source) 
    at org.apache.derby.impl.jdbc.EmbedConnection.prepareStatement(Unknown Source) 
    at org.apache.derby.impl.jdbc.EmbedConnection.prepareStatement(Unknown Source) 
    at [line 3 of snippet above] 

正如你所看到的,這是從準備好的語句被創建的那一行拋出 - 它沒有得到執行它的程度。我究竟做錯了什麼?完全相同的準備語句在PostgreSQL中正常工作。

[編輯] 的derby.log:

---------------------------------------------------------------- 
2010-08-18 08:47:08.779 GMT: 
Booting Derby version The Apache Software Foundation - Apache Derby - 10.6.1.0 - (938214): instance a816c00e-012a-8461-611c-0000046700d0 
on database directory /path/to/myDatabase with class loader [email protected] 

Database Class Loader started - derby.database.classpath='' 
2010-08-18 08:47:12.067 GMT Thread[SwingWorker-pool-1-thread-1,5,main] (XID = 316), (SESSIONID = 1), (DATABASE = myDatabase), (DRDAID = null), Cleanup action starting 
2010-08-18 08:47:12.067 GMT Thread[SwingWorker-pool-1-thread-1,5,main] (XID = 316), (SESSIONID = 1), (DATABASE = myDatabase), (DRDAID = null), Failed Statement is: INSERT INTO input_files (job_id, hash) SELECT job_id, ? FROM job WHERE job_name = ? 
java.lang.NullPointerException 
    at org.apache.derby.impl.sql.compile.BitTypeCompiler.storable(Unknown Source) 
    at org.apache.derby.impl.sql.compile.ResultColumn.checkStorableExpression(Unknown Source) 
    at org.apache.derby.impl.sql.compile.ResultColumn.checkStorableExpression(Unknown Source) 
    at org.apache.derby.impl.sql.compile.ResultColumnList.checkStorableExpressions(Unknown Source) 
    at org.apache.derby.impl.sql.compile.InsertNode.bindStatement(Unknown Source) 
    at org.apache.derby.impl.sql.GenericStatement.prepMinion(Unknown Source) 
    at org.apache.derby.impl.sql.GenericStatement.prepare(Unknown Source) 
    at org.apache.derby.impl.sql.conn.GenericLanguageConnectionContext.prepareInternalStatement(Unknown Source) 
    at org.apache.derby.impl.jdbc.EmbedPreparedStatement.<init>(Unknown Source) 
    at org.apache.derby.impl.jdbc.EmbedPreparedStatement20.<init>(Unknown Source) 
    at org.apache.derby.impl.jdbc.EmbedPreparedStatement30.<init>(Unknown Source) 
    at org.apache.derby.impl.jdbc.EmbedPreparedStatement40.<init>(Unknown Source) 
    at org.apache.derby.jdbc.Driver40.newEmbedPreparedStatement(Unknown Source) 
    at org.apache.derby.impl.jdbc.EmbedConnection.prepareStatement(Unknown Source) 
    at org.apache.derby.impl.jdbc.EmbedConnection.prepareStatement(Unknown Source) 
    at [line 3 of snippet] 
Cleanup action completed 

2010-08-18 08:47:12.084 GMT: 
Shutting down instance a816c00e-012a-8461-611c-0000046700d0 with class loader [email protected] 
---------------------------------------------------------------- 

,並展開例外:

java.sql.SQLException: Java exception: ': java.lang.NullPointerException'. 
    at org.apache.derby.impl.jdbc.SQLExceptionFactory40.getSQLException(Unknown Source) 
    at org.apache.derby.impl.jdbc.Util.newEmbedSQLException(Unknown Source) 
    at org.apache.derby.impl.jdbc.Util.javaException(Unknown Source) 
    at org.apache.derby.impl.jdbc.TransactionResourceImpl.wrapInSQLException(Unknown Source) 
    at org.apache.derby.impl.jdbc.TransactionResourceImpl.handleException(Unknown Source) 
    at org.apache.derby.impl.jdbc.EmbedConnection.handleException(Unknown Source) 
    at org.apache.derby.impl.jdbc.ConnectionChild.handleException(Unknown Source) 
    at org.apache.derby.impl.jdbc.EmbedPreparedStatement.<init>(Unknown Source) 
    at org.apache.derby.impl.jdbc.EmbedPreparedStatement20.<init>(Unknown Source) 
    at org.apache.derby.impl.jdbc.EmbedPreparedStatement30.<init>(Unknown Source) 
    at org.apache.derby.impl.jdbc.EmbedPreparedStatement40.<init>(Unknown Source) 
    at org.apache.derby.jdbc.Driver40.newEmbedPreparedStatement(Unknown Source) 
    at org.apache.derby.impl.jdbc.EmbedConnection.prepareStatement(Unknown Source) 
    at org.apache.derby.impl.jdbc.EmbedConnection.prepareStatement(Unknown Source) 
    at [line 3 of snippet above] 
Caused by: java.sql.SQLException: Java exception: ': java.lang.NullPointerException'. 
    at org.apache.derby.impl.jdbc.SQLExceptionFactory.getSQLException(Unknown Source) 
    at org.apache.derby.impl.jdbc.SQLExceptionFactory40.wrapArgsForTransportAcrossDRDA(Unknown Source) 
... 26 more 
Caused by: java.lang.NullPointerException 
    at org.apache.derby.impl.sql.compile.BitTypeCompiler.storable(Unknown Source) 
    at org.apache.derby.impl.sql.compile.ResultColumn.checkStorableExpression(Unknown Source) 
    at org.apache.derby.impl.sql.compile.ResultColumn.checkStorableExpression(Unknown Source) 
    at org.apache.derby.impl.sql.compile.ResultColumnList.checkStorableExpressions(Unknown Source) 
    at org.apache.derby.impl.sql.compile.InsertNode.bindStatement(Unknown Source) 
    at org.apache.derby.impl.sql.GenericStatement.prepMinion(Unknown Source) 
    at org.apache.derby.impl.sql.GenericStatement.prepare(Unknown Source) 
    at org.apache.derby.impl.sql.conn.GenericLanguageConnectionContext.prepareInternalStatement(Unknown Source) 
... 19 more 
SQLState: XJ001 
Error code: 0 
Message: Java exception: ': java.lang.NullPointerException'. 
Cause: java.sql.SQLException: Java exception: ': java.lang.NullPointerException'. 
    at org.apache.derby.impl.jdbc.SQLExceptionFactory.getSQLException(Unknown Source) 
    at org.apache.derby.impl.jdbc.SQLExceptionFactory40.wrapArgsForTransportAcrossDRDA(Unknown Source) 
    at org.apache.derby.impl.jdbc.SQLExceptionFactory40.getSQLException(Unknown Source) 
    at org.apache.derby.impl.jdbc.Util.newEmbedSQLException(Unknown Source) 
    at org.apache.derby.impl.jdbc.Util.javaException(Unknown Source) 
    at org.apache.derby.impl.jdbc.TransactionResourceImpl.wrapInSQLException(Unknown Source) 
    at org.apache.derby.impl.jdbc.TransactionResourceImpl.handleException(Unknown Source) 
    at org.apache.derby.impl.jdbc.EmbedConnection.handleException(Unknown Source) 
    at org.apache.derby.impl.jdbc.ConnectionChild.handleException(Unknown Source) 
    at org.apache.derby.impl.jdbc.EmbedPreparedStatement.<init>(Unknown Source) 
    at org.apache.derby.impl.jdbc.EmbedPreparedStatement20.<init>(Unknown Source) 
    at org.apache.derby.impl.jdbc.EmbedPreparedStatement30.<init>(Unknown Source) 
    at org.apache.derby.impl.jdbc.EmbedPreparedStatement40.<init>(Unknown Source) 
    at org.apache.derby.jdbc.Driver40.newEmbedPreparedStatement(Unknown Source) 
    at org.apache.derby.impl.jdbc.EmbedConnection.prepareStatement(Unknown Source) 
    at org.apache.derby.impl.jdbc.EmbedConnection.prepareStatement(Unknown Source) 
    at [line 3 of snippet above] 
Caused by: java.lang.NullPointerException 
    at org.apache.derby.impl.sql.compile.BitTypeCompiler.storable(Unknown Source) 
    at org.apache.derby.impl.sql.compile.ResultColumn.checkStorableExpression(Unknown Source) 
    at org.apache.derby.impl.sql.compile.ResultColumn.checkStorableExpression(Unknown Source) 
    at org.apache.derby.impl.sql.compile.ResultColumnList.checkStorableExpressions(Unknown Source) 
    at org.apache.derby.impl.sql.compile.InsertNode.bindStatement(Unknown Source) 
    at org.apache.derby.impl.sql.GenericStatement.prepMinion(Unknown Source) 
    at org.apache.derby.impl.sql.GenericStatement.prepare(Unknown Source) 
    at org.apache.derby.impl.sql.conn.GenericLanguageConnectionContext.prepareInternalStatement(Unknown Source) 
... 19 more 
Cause: java.lang.NullPointerException 
    at org.apache.derby.impl.sql.compile.BitTypeCompiler.storable(Unknown Source) 
    at org.apache.derby.impl.sql.compile.ResultColumn.checkStorableExpression(Unknown Source) 
    at org.apache.derby.impl.sql.compile.ResultColumn.checkStorableExpression(Unknown Source) 
    at org.apache.derby.impl.sql.compile.ResultColumnList.checkStorableExpressions(Unknown Source) 
    at org.apache.derby.impl.sql.compile.InsertNode.bindStatement(Unknown Source) 
    at org.apache.derby.impl.sql.GenericStatement.prepMinion(Unknown Source) 
    at org.apache.derby.impl.sql.GenericStatement.prepare(Unknown Source) 
    at org.apache.derby.impl.sql.conn.GenericLanguageConnectionContext.prepareInternalStatement(Unknown Source) 
    at org.apache.derby.impl.jdbc.EmbedPreparedStatement.<init>(Unknown Source) 
    at org.apache.derby.impl.jdbc.EmbedPreparedStatement20.<init>(Unknown Source) 
    at org.apache.derby.impl.jdbc.EmbedPreparedStatement30.<init>(Unknown Source) 
    at org.apache.derby.impl.jdbc.EmbedPreparedStatement40.<init>(Unknown Source) 
    at org.apache.derby.jdbc.Driver40.newEmbedPreparedStatement(Unknown Source) 
    at org.apache.derby.impl.jdbc.EmbedConnection.prepareStatement(Unknown Source) 
    at org.apache.derby.impl.jdbc.EmbedConnection.prepareStatement(Unknown Source) 
    at [line 3 of snippet above] 

回答

2

這方面的一個空指針異常 - 特別是如果相同的JDBC代碼工作與其他DBMS - 外觀就像您在Derby JDBC驅動程序中遇到了一個錯誤。即使您犯了錯誤並傳遞了錯誤的數據或空指針,驅動程序也應該檢測並報告錯誤,而不是崩潰。

+0

我同意,這看起來像德比的錯誤。通過展開異常鏈,您可能可以獲得更多信息(即更完整的堆棧跟蹤):http://wiki.apache.org/db-derby/UnwindExceptionChain 另外,請查看derby.log更多信息。 – 2010-08-17 17:14:44

+0

提交的問題:https://issues.apache.org/jira/browse/DERBY-4780 – Scott 2010-08-18 09:41:10

+0

爲了記錄,顯然這是一個已知的錯誤,並且已經在Derby源代碼中修復。解決方法是在參數周圍添加一個轉換 - 即:INSERT INTO input_files(job_ID,hash)SELECT job_id,CAST(?as CHAR(16)FOR BIT DATA)FROM job WHERE job_name =?' – Scott 2010-08-18 11:53:09

0
PreparedStatement s = con.prepareStatement("INSERT INTO input_files (job_ID, hash) SELECT job_id, ? FROM job WHERE job_name = ?"); 

「job_ID」與「job_id」匹配大小寫,看看是否可以解決問題。

+0

沒有快樂。無論如何,我認爲SQL不區分大小寫。 – Scott 2010-08-17 15:32:56

+0

@Scott:除非您使用分隔標識符(標準中的雙引號,MS SQL Server中的方括號,MySQL中的後退標記等),否則SQL不區分大小寫。 – 2010-08-18 00:08:25

1

我懷疑你不能直接將文字哈希碼插入到選擇列列表中,因爲Derby不明白你想在那裏放置一個文字值,而不是列名。

一個合理的解決方法可能是重新編寫您的應用程序以從正在讀取SELECT值的循環內執行INSERT語句。一些沿線:

updateStatement = prepareStatement("insert into input_files (job_id, hash) values (?,?)") 
ResultSet rs = executeQuery("select job_id from job where job_name = ?") 
while (rs.next()) 
    updateStatement.setString(1, rs.getString(1)) 
    updateStatement.setBytes(2, md5sum) 
    updateStatement.executeUpdate() 
+0

作爲一種解決方法,我認爲這是我們最終要做的。實際上,我們在幾個地方做類似的查詢,所以如果我們緩存job_id的值,我們實際上可能會最終提高我們的數據庫性能。 – Scott 2010-08-18 09:43:33