5

Java から Windows 32 ビットの Access データベースにデータを書き込んでいます。レコードを書き込むときは、行 ID/主キーを取得して、a) 必要に応じてレコードを簡単に更新し、b) 他のデータをそのレコードに相互参照できるようにする必要があります。

C で似たようなことをすると、新しいレコードを書き込み、同時に行 ID を取得できる更新可能なカーソルを作成できました。Java では、これを行うことができるように見えますが、次のコードで例外がスローされます。

    con = openAccessDatabase();
    String selectString = "SELECT ID, RunCount FROM SpeedTable";
    try {
        PreparedStatement selectStatement = con.prepareStatement(selectString, 
                ResultSet.TYPE_SCROLL_INSENSITIVE,
                ResultSet.CONCUR_UPDATABLE);
        ResultSet idResult = selectStatement.executeQuery();
        int id;
        for (int i = 0; i < nWrites; i++) {
            idResult.moveToInsertRow();
            idResult.updateObject(1, null); // this line makes no difference whatsoever !
            idResult.updateInt(2, i);
            idResult.insertRow(); // throws java.sql.SQLException: [Microsoft][ODBC Microsoft Access Driver]Error in row
            id = idResult.getInt(1);
        }
        selectStatement.close();
    } catch (SQLException e) {
        e.printStackTrace();
    }

私ができる唯一のことは、新しいレコードを書き込んでから、別のクエリを実行して行 ID を取得することです...

    String insertString = "INSERT INTO SpeedTable (RunCount) VALUES (?)";
    String idString = "SELECT ID FROM SpeedTable ORDER BY ID DESC";
    //      
    try {
        ResultSet idResult = null;
        PreparedStatement preparedStatement, idStatement;
        preparedStatement = con.prepareStatement(insertString,
                ResultSet.TYPE_FORWARD_ONLY,
                ResultSet.CONCUR_READ_ONLY);
        idStatement = con.prepareStatement(idString, 
                ResultSet.TYPE_FORWARD_ONLY,
                ResultSet.CONCUR_READ_ONLY);

        for (int i = 0; i < nWrites; i++) {
            // write the data into the database
            preparedStatement.setInt(1, i);
            preparedStatement.execute();
            // re-run the query to get the index back from the database. 
            idResult = idStatement.executeQuery();
            idResult.next();
            int lastIndex = idResult.getInt(1);
            idResult.close();
        }

これは機能しますが、テーブルに数十から数千のレコードが含まれていると、信じられないほど遅くなります。プログラムの 2 つの部分が同時に書き込みを開始すると、間違った ID が返される危険性もあります (可能性は低いですが、不可能ではありません)。

少なくとも 1 つの提案は、Java を使用しないか、Access を使用しないかのいずれかであることはわかっていますが、それらはオプションではありません。これは無料のオープン ソース ソフトウェア パッケージの一部でもあるので、何かにお金を払うのは気が進まない. アプリケーションに必要な基本機能を提供する独自の C JNI インターフェースを作成することは、さらに魅力的ではありません。

4

1 に答える 1

0

これがMSAccessで機能するかどうかはわかりませんが、次のことを試すことができます。

st.executeUpdate("INSERT INTO SpeedTable (RunCount) VALUES (1000)", Statement.RETURN_GENERATED_KEYS);
ResultSet rs = st.getGeneratedKeys();
rs.next();
long id = rs.getLong(1);
于 2012-11-23T06:26:35.963 に答える