首页 > 解决方案 > 使用 Oracle 瘦 JDBC 执行 PreparedStatement 时出现 AssertionError

问题描述

我在使用 Oracle 的瘦 JDBC 驱动程序 (ojdbc7) 的 PreparedStatements 中遇到了一个奇怪的(看起来像一个)错误。多次执行 PreparedStatement 时会发生 AssertionError,并且似乎与设置空绑定值有关。

这是演示这一点的测试代码的摘录:

  private void insertRows(String tableName) throws SQLException
  {
    String insertSQL = 
      "INSERT INTO "
          + tableName
          + " (objectid, attributeid, sequence, value)"
          + " VALUES (?, ?, ?, ?)";
    PreparedStatement stmt = m_Conn.prepareStatement(insertSQL);
    
    // insert first 3 rows with same objId and attrId
    long objId = 700;
    long attrId = 701;
    int seq = 1;

    stmt.setLong(1, objId);
    stmt.setLong(2, attrId);

    // 1st row (non-null value)
    stmt.setInt(3, seq++);
    stmt.setString(4, "Foo");
    stmt.execute();

    // 2nd row (null value)
    stmt.setInt(3, seq++);
    stmt.setNull(4, Types.VARCHAR);
    stmt.execute();

    // 3rd row (null value)
    stmt.setInt(3, seq++);
    stmt.setNull(4, Types.VARCHAR);
    stmt.execute();

    // insert next 2 rows with new objId and attrId
    objId = 800;
    attrId = 801;
    seq = 1;

    stmt.setLong(1, objId);
    stmt.setLong(2, attrId);

    // 1st row (null value)
    stmt.setInt(3, seq++);
    stmt.setNull(4, Types.VARCHAR);
    stmt.execute();

    // 2nd row (non-null value)
    stmt.setInt(3, seq++);
    stmt.setString(4, "Bar");
    stmt.execute();  // this results in an AssertionError

    System.out.println("Inserts were successful");
    stmt.close();
  }

PreparedStatement 的第 5 次执行导致 AssertionError:

Expected AssertionError: java.lang.AssertionError: lastOffset: 5        leastOffset: 5  indexOfLeastOffet: 3
java.lang.AssertionError: lastOffset: 5 leastOffset: 5  indexOfLeastOffet: 3
        at oracle.jdbc.driver.OraclePreparedStatement.compressLastBoundData(OraclePreparedStatement.java:1902)
        at oracle.jdbc.driver.OraclePreparedStatement.setupDbaBindBuffers(OraclePreparedStatement.java:3062)
        at oracle.jdbc.driver.OraclePreparedStatement.setupBindBuffers(OraclePreparedStatement.java:3046)
        at oracle.jdbc.driver.OraclePreparedStatement.processCompletedBindRow(OraclePreparedStatement.java:2670)
        at oracle.jdbc.driver.OraclePreparedStatement.executeInternal(OraclePreparedStatement.java:4790)
        at oracle.jdbc.driver.OraclePreparedStatement.execute(OraclePreparedStatement.java:4901)
        at oracle.jdbc.driver.OraclePreparedStatementWrapper.execute(OraclePreparedStatementWrapper.java:1385)
        at oracle.Dave.Bug912.insertRows(Bug912.java:130)
        at oracle.Dave.Bug912.main(Bug912.java:38)

AssertionError 仅在绑定值设置的特定组合时出现,并且似乎与空值的设置有关(如果不使用空值,则不会出现该错误)。它也不会在禁用断言的情况下发生(显然)。数据库版本似乎无关紧要——我已经在 11.2 和 12.1 中看到了这一点。

有没有人见过这种错误?如果有人感兴趣,我可以附上一个完整的测试用例。

标签: javaoraclejdbc

解决方案


推荐阅读