2010-08-17 2 views
2

Я пишу приложение Java, которое работает с Apache Derby через JDBC. У меня возникли проблемы с кодом в следующем фрагменте: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 работает с другими СУБД - внешний вид например, вы попали в ошибку в драйвере Derby JDBC. Даже если вы допустили ошибку и передали ошибочные данные или нулевой указатель, драйвер должен обнаружить это и сообщить об ошибке, а не сбой.

+0

Согласен, это похоже на ошибку в Дерби. Вероятно, вы можете получить дополнительную информацию (то есть более полную трассировку стека), отключив цепочку исключений: http://wiki.apache.org/db-derby/UnwindExceptionChain Также посмотрите в derby.log для больше информации. –

+0

Ошибка: https://issues.apache.org/jira/browse/DERBY-4780 – Scott

+0

Для записи, по-видимому, это была известная ошибка, и она была исправлена ​​в источнике Derby. Работа вокруг заключается в том, чтобы добавить бросок вокруг параметра - то есть 'INSERT INTO input_files (job_ID, hash) SELECT job_id, CAST (? Как CHAR (16) ДЛЯ ДАННЫХ BIT) FROM job WHERE job_name =?' – Scott

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

«job_ID» vs «job_id» соответствует случаю и видит, исправляет проблему.

+0

Нет радости. В любом случае, я думал, что SQL не зависит от регистра. – Scott

+0

@Scott: SQL не зависит от регистра, если вы не используете идентификаторы с разделителями (двойные кавычки в стандартном, квадратные скобки в MS SQL Server, обратные тики в MySQL и т. Д.). –

1

Я подозреваю, что вы не сможете замять буквенный хэш-код непосредственно в списке столбцов выбора, потому что Derby не понимает, что вы хотите разместить там буквальное значение, а не имя столбца.

Разумным решением может быть перекодирование вашего приложения для выполнения инструкции INSERT из цикла, который считывает значения из SELECT. Что-то вроде:

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

Смежные вопросы