【问题标题】:ORMLite Issue with inserting tables from one database to another database on Android在Android上将表从一个数据库插入另一个数据库的ORMLite问题
【发布时间】:2013-09-13 16:23:44
【问题描述】:

我正在将 SQLite 数据库文件从服务器下载到用户的 Android 设备。下载后,我使用下载的数据库在本地数据库中插入或替换一些表。我为此使用 ORMLite 4.47。

首先我将数据库文件附加到 DatabaseConnection:

DatabaseConnection con = null;
con = conSrc.getReadWriteConnection();
con.executeStatement("attach database '" + localDatabase.getAbsolutePath() + "' as '" + localDb + "'", DatabaseConnection.DEFAULT_RESULT_FLAGS);
con.executeStatement("attach database '" + downloadedDatabase.getAbsolutePath() + "' as '" + remoteDb + "'", DatabaseConnection.DEFAULT_RESULT_FLAGS);

附加数据库后,我创建以下查询以从下载的数据库(remoteDb)复制到本地数据库(localDb):

INSERT OR REPLACE INTO localDb.table_items (createdAt_device, updatedAt_device, _id, column_1, column_2, column_3, column_4, column_5, column_6) SELECT createdAt_device, updatedAt_device, _id, column_1, column_2, column_3, column_4, column_5, column_6 FROM remoteDb.table_items

之后,我从 ORMLite 执行以下函数:

con.executeStatement(query, flags); 

该函数在 Android 4.1(带有 SQLite 3.7.11)及更高版本上运行良好。但我在 Android 4.0 和 4.0.3(使用 SQLite 3.7.4)上收到以下错误:

09-13 15:51:19.852: E/com.example.controller(1028): java.sql.SQLException: Problems executing INSERT OR REPLACE INTO localDb.table_items (createdAt_device, updatedAt_device, _id, column_1, column_2, column_3, column_4, column_5, column_6) SELECT createdAt_device, updatedAt_device, _id, column_1, column_2, column_3, column_4, column_5, column_6 FROM remoteDb.table_items Android statement: INSERT OR REPLACE INTO localDb.table_items (createdAt_device, updatedAt_device, _id, column_1, column_2, column_3, column_4, column_5, column_6) SELECT createdAt_device, updatedAt_device, _id, column_1, column_2, column_3, column_4, column_5, column_6 FROM remoteDb.table_items
09-13 15:51:19.852: E/com.example.controller(1028):     at com.j256.ormlite.misc.SqlExceptionUtil.create(SqlExceptionUtil.java:22)
09-13 15:51:19.852: E/com.example.controller(1028):     at com.j256.ormlite.android.AndroidCompiledStatement.execSql(AndroidCompiledStatement.java:185)
09-13 15:51:19.852: E/com.example.controller(1028):     at com.j256.ormlite.android.AndroidDatabaseConnection.executeStatement(AndroidDatabaseConnection.java:134)
09-13 15:51:19.852: E/com.example.controller(1028):     at com.example.controller$DatabaseTransferHandler.executeDatabaseTransfers(contoller.java:763)
09-13 15:51:19.852: E/com.example.controller(1028):     at com.example.controller$DatabaseTransferHandler.access$0(contoller.java:740)
09-13 15:51:19.852: E/com.example.controller(1028):     at com.example.controller.transferTables(contoller.java:494)
09-13 15:51:19.852: E/com.example.controller(1028):     at com.example.controller.addElement(contoller.java:132)
09-13 15:51:19.852: E/com.example.controller(1028):     at com.example.controller.addOrRemoveElements(contoller.java:109)
09-13 15:51:19.852: E/com.example.controller(1028):     at com.example.controller.addElements(contoller.java:147)
09-13 15:51:19.852: E/com.example.controller(1028):     at com.example.controller.download(contoller.java:254)
09-13 15:51:19.852: E/com.example.controller(1028):     at com.example.controller.access$3(controller.java:204)
09-13 15:51:19.852: E/com.example.controller(1028):     at com.example.controller$2.doInBackground(contoller.java:468)
09-13 15:51:19.852: E/com.example.controller(1028):     at com.example.controller$2.doInBackground(contoller.java:1)
09-13 15:51:19.852: E/com.example.controller(1028):     at android.os.AsyncTask$2.call(AsyncTask.java:264)
09-13 15:51:19.852: E/com.example.controller(1028):     at java.util.concurrent.FutureTask$Sync.innerRun(FutureTask.java:305)
09-13 15:51:19.852: E/com.example.controller(1028):     at java.util.concurrent.FutureTask.run(FutureTask.java:137)
09-13 15:51:19.852: E/com.example.controller(1028):     at android.os.AsyncTask$SerialExecutor$1.run(AsyncTask.java:208)
09-13 15:51:19.852: E/com.example.controller(1028):     at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1076)
09-13 15:51:19.852: E/com.example.controller(1028):     at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:569)
09-13 15:51:19.852: E/com.example.controller(1028):     at java.lang.Thread.run(Thread.java:856)
09-13 15:51:19.852: E/com.example.controller(1028): Caused by: android.database.sqlite.SQLiteDatabaseLockedException: database is locked
09-13 15:51:19.852: E/com.example.controller(1028):     at android.database.sqlite.SQLiteStatement.native_executeSql(Native Method)
09-13 15:51:19.852: E/com.example.controller(1028):     at android.database.sqlite.SQLiteStatement.executeUpdateDelete(SQLiteStatement.java:90)
09-13 15:51:19.852: E/com.example.controller(1028):     at android.database.sqlite.SQLiteDatabase.executeSql(SQLiteDatabase.java:1899)
09-13 15:51:19.852: E/com.example.controller(1028):     at android.database.sqlite.SQLiteDatabase.execSQL(SQLiteDatabase.java:1839)
09-13 15:51:19.852: E/com.example.controller(1028):     at android.database.sqlite.SQLiteDatabase.beginTransaction(SQLiteDatabase.java:661)
09-13 15:51:19.852: E/com.example.controller(1028):     at android.database.sqlite.SQLiteDatabase.beginTransactionNonExclusive(SQLiteDatabase.java:576)
09-13 15:51:19.852: E/com.example.controller(1028):     at android.database.sqlite.SQLiteStatement.acquireAndLock(SQLiteStatement.java:247)
09-13 15:51:19.852: E/com.example.controller(1028):     at android.database.sqlite.SQLiteStatement.executeUpdateDelete(SQLiteStatement.java:84)
09-13 15:51:19.852: E/com.example.controller(1028):     at android.database.sqlite.SQLiteDatabase.executeSql(SQLiteDatabase.java:1899)
09-13 15:51:19.852: E/com.example.controller(1028):     at android.database.sqlite.SQLiteDatabase.execSQL(SQLiteDatabase.java:1889)
09-13 15:51:19.852: E/com.example.controller(1028):     at com.j256.ormlite.android.AndroidCompiledStatement.execSql(AndroidCompiledStatement.java:183)
09-13 15:51:19.852: E/com.example.controller(1028):     ... 18 more

我该如何解决这个问题?有没有更好的方法可以将大量信息下载到设备上?

【问题讨论】:

    标签: android database sqlite insert ormlite


    【解决方案1】:

    我是这个问题的作者的同事,我设法找到了避免这个问题的方法。我想我会把它贴在这里,以防其他人遇到同样的问题。

    具有该非常特定操作系统版本的 Android 设备似乎在使用此 Ormlite 命令序列时存在问题:

    DatabaseConnection con = null;
    con = conSrc.getReadWriteConnection();
    con.executeStatement("attach database '" + localDatabase.getAbsolutePath() + "' as '" + localDb + "'", DatabaseConnection.DEFAULT_RESULT_FLAGS);
    con.executeStatement("attach database '" + downloadedDatabase.getAbsolutePath() + "' as '" + remoteDb + "'", DatabaseConnection.DEFAULT_RESULT_FLAGS);
    

    我不知道这是由这些设备上预装的 SQLite3 版本引起的,还是由其他原因引起的。

    现在我们可以避免这种情况,因为我们可以(幸运地)完全避免在这种情况下使用 Ormlite。 SQLite 语句“ATTACH DATABASE”不需要在 DatabaseConnection 实例上执行 - 它可以在本地数据库文件上执行。因此,不需要前一个块,只需要这个语句:

    db.execSQL("ATTACH DATABASE '" + tempDb.getAbsolutePath() + "' AS '" + remoteDb + "'");
    

    其中db 是本地数据库的SQLiteDatabase 实例。 SQLite documentation 声明:

    “ATTACH DATABASE 语句将另一个数据库文件添加到当前数据库连接。”

    这就是为什么不需要DatabaseConnection 实例的原因。

    【讨论】:

    • 我不太了解这个 Matthias,但如果 ORMLite 需要在这里做些什么来让它变得更好,请告诉我。
    猜你喜欢
    • 1970-01-01
    • 2014-11-21
    • 2023-04-10
    • 2015-03-31
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多