在(JDBC-)ODBC下使用已保存的Access参数查询

时间:2015-08-26 10:41:33

标签: java ms-access jdbc nullpointerexception jdbc-odbc

在我的Java应用程序中,我必须使用来自Access 2010数据库的数据。我使用Access中的图形查询创建器来创建适当的查询,它运行良好。

不幸的是,当我尝试在我的Java应用程序中使用带有该查询的预准备语句(为了使用参数)时,我得到了一个N​​PE

messageChildrenRequest.setString(1, blockId);
ResultSet result = messageChildrenRequest.executeQuery();

当我使用setString()设置参数并且我的查询未执行但是当我查看调试器时语句不为空时,会发生NPE ...

我的访问权限是:

SELECT IRSIDD.[BLOCK ID], IRSIDD.[IDENTIFICATION CHIFFREE], IRSIDD.MSG_ID, MAIN.SUB_FIELD_ID, MAIN.ORDER, FIELD.[FIELD NAME], FIELD.TYPE, FIELD.[RC 'TYPE] "
FROM IRSIDD LEFT JOIN (MAIN LEFT JOIN FIELD ON MAIN.SUB_FIELD_ID = FIELD.[FIELD ID]) ON IRSIDD.[BLOCK ID] = MAIN.BLOCK_ID "
WHERE ((IRSIDD.[BLOCK ID])=?)

StackTrace给了我:

Exception in thread "main" 
java.lang.NullPointerException
    at sun.jdbc.odbc.JdbcOdbcPreparedStatement.clearParameter(Unknown Source)
    at sun.jdbc.odbc.JdbcOdbcPreparedStatement.setChar(Unknown Source)
    at sun.jdbc.odbc.JdbcOdbcPreparedStatement.setString(Unknown Source) 

当我尝试一个非常简单的预备声明时:

SELECT * FROM table1 WHERE table1.id = ?

设置参数时我没有得到任何NPE,所以我怀疑Access和java JDBC没有相同的方式来处理连接。

有人已经出现过那种问题,或者可以确认我的查询结构是否存在问题?

2 个答案:

答案 0 :(得分:0)

Connection connection = null;
CallableStatement callStmt = null;
String myParam = "test";
String statement = "SELECT * FROM table1 WHERE table1.id = ?";
try {
connection = DatabasePoolUtil.getDefaultConnection(); //Connects
callStmt = connection.prepareCall(statement);
callStmt.setString(1,myParam);
callStmt.execute();
}
catch (SQLException ex) {
// Do something
}
finally { // connection has to be closed
if (callStmt != null) {
 callStmt.close();
  }
 if (connection != null) {
 connection.close();
}
}

答案 1 :(得分:0)

与Access数据库的ODBC(和OLEDB)接口将不同类型的已保存Access查询公开为“视图”或“存储过程”:

Access query                     appears under ODBC/OLEDB as
-------------------------------  ---------------------------
Select query without parameters  View
Select query with parameters     Stored Procedure
Append query (INSERT)            Stored Procedure
Update query                     Stored Procedure
Delete query                     Stored Procedure

由于Access保存的查询具有参数,因此它看起来像ODBC下的存储过程,因此您需要使用CallableStatement来处理它。

例如,给定以下保存的参数查询,在Access

中命名为[myParameterQuery]
PARAMETERS specificID Long;
SELECT Table1.*
FROM Table1
WHERE (((Table1.ID)=[specificID]));

我们需要使用以下Java代码来检索ID = 3的行:

String connectionString = "jdbc:odbc:"
        + "DRIVER={Microsoft Access Driver (*.mdb, *.accdb)};"
        + "DBQ=C:/Users/Public/32224442.accdb;";
try (Connection conn = DriverManager.getConnection(connectionString)) {
    try (CallableStatement cs = conn.prepareCall("{call myParameterQuery(?)}")) {
        cs.setInt(1, 3);  // set "specificID" parameter to 3
        try (ResultSet rs = cs.executeQuery()) {
            rs.next();
            System.out.println(rs.getInt(1));
        }
    }
} catch (Exception e) {
    System.err.println(e.getMessage());
    System.exit(0);
}

相应的C#代码为:

string myConnectionString =
        @"Driver={Microsoft Access Driver (*.mdb, *.accdb)};" +
        @"Dbq=C:\Users\Public\32224442.accdb;";
using (var con = new OdbcConnection(myConnectionString))
{
    con.Open();
    using (var cmd = new OdbcCommand("{CALL myParameterQuery (?)}", con))
    {
        cmd.CommandType = System.Data.CommandType.StoredProcedure;
        cmd.Parameters.Add("?", OdbcType.Int).Value = 3;  // set "specificID" parameter to 3
        using (OdbcDataReader rdr = cmd.ExecuteReader())
        {
            rdr.Read();
            Console.WriteLine(rdr[0]);
        }
    }
}