0

Dao.setAutoCommit()の使用方法の指示に従いましたか?自動コミットを無効にして、コミットをバッチで実行できるようにします。

実際にコードを実行しようとすると、プログラムはDAOでcreateや同様の操作を呼び出した回数を追跡し、バッチサイズよりも大きい場合は、dao.commit()...を呼び出します。次に、このエラーが発生します(SaveJsonParserは、コードを含むクラスの名前です)。

06-08 17:18:50.866:E / AndroidRuntime(30993):java.lang.Runtime

Exception: An error occured while executing doInBackground()
06-08 17:18:50.866: E/AndroidRuntime(30993):    at android.os.AsyncTask$3.done(AsyncTask.java:200)
06-08 17:18:50.866: E/AndroidRuntime(30993):    at java.util.concurrent.FutureTask$Sync.innerSetException(FutureTask.java:274)
06-08 17:18:50.866: E/AndroidRuntime(30993):    at java.util.concurrent.FutureTask.setException(FutureTask.java:125)
06-08 17:18:50.866: E/AndroidRuntime(30993):    at java.util.concurrent.FutureTask$Sync.innerRun(FutureTask.java:308)
06-08 17:18:50.866: E/AndroidRuntime(30993):    at java.util.concurrent.FutureTask.run(FutureTask.java:138)
06-08 17:18:50.866: E/AndroidRuntime(30993):    at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1088)
06-08 17:18:50.866: E/AndroidRuntime(30993):    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:581)
06-08 17:18:50.866: E/AndroidRuntime(30993):    at java.lang.Thread.run(Thread.java:1019)
06-08 17:18:50.866: E/AndroidRuntime(30993): Caused by: java.lang.IllegalStateException: no transaction pending
06-08 17:18:50.866: E/AndroidRuntime(30993):    at android.database.sqlite.SQLiteDatabase.setTransactionSuccessful(SQLiteDatabase.java:673)
06-08 17:18:50.866: E/AndroidRuntime(30993):    at com.j256.ormlite.android.AndroidDatabaseConnection.commit(AndroidDatabaseConnection.java:77)
06-08 17:18:50.866: E/AndroidRuntime(30993):    at com.j256.ormlite.dao.BaseDaoImpl.commit(BaseDaoImpl.java:811)
06-08 17:18:50.866: E/AndroidRuntime(30993):    at com.visitsanantonio.save.data.SaveJsonParser.commitCategories(SaveJsonParser.java:412)
06-08 17:18:50.866: E/AndroidRuntime(30993):    at com.visitsanantonio.save.data.SaveJsonParser.parseDeal(SaveJsonParser.java:278)
06-08 17:18:50.866: E/AndroidRuntime(30993):    at com.visitsanantonio.save.data.SaveJsonParser.parseNewUpdatedDeals(SaveJsonParser.java:233)
06-08 17:18:50.866: E/AndroidRuntime(30993):    at com.visitsanantonio.save.data.SaveJsonParser$JsonParsingTask.doInBackground(SaveJsonParser.java:479)
06-08 17:18:50.866: E/AndroidRuntime(30993):    at com.visitsanantonio.save.data.SaveJsonParser$JsonParsingTask.doInBackground(SaveJsonParser.java:1)
06-08 17:18:50.866: E/AndroidRuntime(30993):    at android.os.AsyncTask$2.call(AsyncTask.java:185)
06-08 17:18:50.866: E/AndroidRuntime(30993):    at java.util.concurrent.FutureTask$Sync.innerRun(FutureTask.java:306)
06-08 17:18:50.866: E/AndroidRuntime(30993):    ... 4 more

いくつかの実験の後、バックグラウンドスレッドで実行されたこのサニタイズされた切り捨てられた例で示されているように、私のコードは実際にはautoCommitを無効にしていないように見えました。

conn = dao.startThreadConnection();
Log.e(TAG, "dao auto commit: " + dao.isAutoCommit(conn));
dao.setAutoCommit(conn, false);
Log.e(TAG, "dao auto commit: " + dao.isAutoCommit(conn));

ログを確認すると、両方のログ行に「true」と表示されていることがわかります。自動コミットするかどうかは実際には変更していません。私は何が間違っているのですか?

4

3 に答える 3

2

グレイの解決策と方法に基づいて...

accountDao.callBatchTasks(connectionSource,
  new Callable<Void>() {
    public Void call() throws SQLException {
        // insert a number of accounts at once
        for (Account account : accountsToInsert) {
           // update our account object
           accountDao.create(account);
        }
        return null;
    }
});

汎用バージョンとして機能する静的メソッドを作成しました。

public static <T, K> void batchCommit(final List<T> objectsToCommit, final Dao<T, K> dao) throws Exception {
    dao.callBatchTasks(new Callable<Void>() {

        @Override
        public Void call() throws Exception {
            for (T obj : objectsToCommit) {
                dao.create(obj);
            }
            return null;
        }
    });
}

これは次のように呼び出すことができます:

'DaoUtil'.batchCommit(accountsToinsert, accountDao);
于 2013-01-25T16:33:16.643 に答える
0

これは、データベース要求をバッチで処理するために私が最終的に思いついたもののサニタイズされたバージョンです。このアプローチはクラッシュせず、データベース要求をバッチで処理するために実際に機能することを願っています(各オブジェクトを個別にコミットしたり、1回のコミットで非常に大量のトランザクションを蓄積しようとしたりする代わりに)。

final static Integer BATCH_SIZE = 100;

int index = 0;

public int processInBatch(final Collection objectsToProcess)
            throws java.sql.SQLException {

    final int len = objectsToProcess.length();

    Callable<Void> callable = new Callable<Void>() {
        @Override
        public Void call() throws Exception {
            int endIndex = index + BATCH_SIZE;
            if (endIndex > len) {
                endIndex = len;
            }
            for (; index < endIndex; index++) {
                MyObject o = objectsToProcess.get(index);
                try {
                    dao.createOrUpdate(o);
                } catch (java.sql.SQLException se) {
                    Log.e(TAG, "error while attempting to add or update myobject with id of " + o.getId(), se);
                }
            }
        return null;
        }
    };

    ConnectionSource source = databaseHelper.getConnectionSource();
    while (index < len) {
        TransactionManager.callInTransaction(source, callable);
    }
}
于 2012-06-11T21:05:51.070 に答える
0

でJavadocをsetAutoCommit()読んでいない(可能性がある)ことを除けば、何も悪いことはしていません。それは述べています:

これは、すべてのデータベースタイプでサポートされているとは限りません。

と。

警告:何をしているのかわからない限り、このメソッドの代わりにdao.callBatchTasks(Callable)を使用する必要がある可能性があります。

残念ながら、自動コミットをサポートしていないデータベースタイプの1つは、AndroidでのSQLiteです。Androidデータベース接続では、コードは何もしません。私は意図的にこれを行いましたが、戻ってORMLiteが正しく、Androidがそれをサポートしていないことを確認します。

バッチモードで多数のコマンドを実行する場合は、代わりにこのdao.callBatchTasks(...)方法を使用することをお勧めします。これをよりよく説明するためにjavadocsを更新し、現在のORMliteコードがAndroidで自動コミットを使用しないことが正しいことを確認するためにテストします。何かのようなもの:

accountDao.callBatchTasks(connectionSource,
  new Callable<Void>() {
    public Void call() throws SQLException {
        // insert a number of accounts at once
        for (Account account : accountsToInsert) {
           // update our account object
           accountDao.create(account);
        }
        return null;
    }
});
于 2012-06-08T22:58:05.623 に答える