【问题标题】:Derby INSERT SELECT null pointer exceptionDerby INSERT SELECT 空指针异常
【发布时间】:2011-03-31 01:02:09
【问题描述】:

我正在编写一个通过 JDBC 与 Apache Derby 一起工作的 Java 应用程序。我在以下 sn-p 中的代码有问题:

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 上也能正常工作。

[编辑] 德比日志:

----------------------------------------------------------------
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 sun.misc.Launcher$AppClassLoader@6d6f0472

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 sun.misc.Launcher$AppClassLoader@6d6f0472 
----------------------------------------------------------------

和展开的异常:

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]

【问题讨论】:

    标签: java sql jdbc derby


    【解决方案1】:

    此上下文中的空指针异常 - 特别是如果相同的 JDBC 代码与另一个 DBMS 一起使用 - 看起来您遇到了 Derby JDBC 驱动程序中的错误。即使您犯了错误并传递了错误的数据或空指针,驱动程序也应该检测到并报告错误,而不是崩溃。

    【讨论】:

    • 我同意,这看起来像是 Derby 中的一个错误。通过展开异常链,您可能可以获得更多信息(即更完整的堆栈跟踪):wiki.apache.org/db-derby/UnwindExceptionChain 另外,请查看 derby.log 以获取更多信息。
    • 作为记录,显然这是一个已知的错误,并已在 Derby 源中修复。解决方法是在参数周围添加一个演员 - 即INSERT INTO input_files (job_ID, hash) SELECT job_id, CAST(? as CHAR(16) FOR BIT DATA) FROM job WHERE job_name = ?
    【解决方案2】:

    我怀疑您无法将文字哈希码直接塞入选择列列表中,因为 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()
    

    【讨论】:

    • 作为一种解决方法,我认为这就是我们最终要做的。我们实际上在几个地方做了类似的查询,所以如果我们缓存 job_id 的值,我们实际上可能最终会提高我们的数据库性能。
    【解决方案3】:
     PreparedStatement s = con.prepareStatement("INSERT INTO input_files (job_ID, hash) SELECT job_id, ? FROM job WHERE job_name = ?");
    

    “job_ID”与“job_id”匹配大小写,看看是否能解决问题。

    【讨论】:

    • 不高兴。无论如何,我认为 SQL 是不区分大小写的。
    • @Scott:SQL 不区分大小写,除非您使用分隔标识符(标准中的双引号、MS SQL Server 中的方括号、MySQL 中的反引号等)。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2012-12-10
    • 2015-07-12
    相关资源
    最近更新 更多