Android 为什么SQLiteOpenHelper会导致IllegalArgumentException数据库未打开?
首先,这里所有类似的帖子都没有帮助 在异步任务中,我检查应用程序启动是否是第一次启动,这意味着我检查是否有数据库。我想通过从表中查询来实现这一点。这就是正在执行的内容:Android 为什么SQLiteOpenHelper会导致IllegalArgumentException数据库未打开?,android,android-sqlite,sqliteopenhelper,Android,Android Sqlite,Sqliteopenhelper,首先,这里所有类似的帖子都没有帮助 在异步任务中,我检查应用程序启动是否是第一次启动,这意味着我检查是否有数据库。我想通过从表中查询来实现这一点。这就是正在执行的内容: @Override public List<Entity> loadAll(Entity markerEntity) { Log.i(TAG, "trying to load all entities of type " + markerEntity.getTable()); List<Ent
@Override
public List<Entity> loadAll(Entity markerEntity)
{
Log.i(TAG, "trying to load all entities of type " + markerEntity.getTable());
List<Entity> results = new LinkedList<Entity>();
SQLiteDatabase db = defaultSQLiteOpenHelper.getWritableDatabase();
Cursor cursor = db.query(markerEntity.getTable(), markerEntity.getAllColumns(), null, null, null, null, null);
cursor.moveToFirst();
while (!cursor.isAfterLast())
{
Entity result = markerEntity.createNewInstance(cursor);
results.add(result);
cursor.moveToNext();
}
db.close();
return results;
}
它正好发生在方法上,请参见下面的createAllTables
报告说:
创建和/或打开将用于读取和
写第一次调用它时,将打开数据库
和onCreateSQLiteDatabase,onUpgradeSQLiteDatabase,int,int
和/或将调用onOpenSQLiteDatabase
在我看来,它应该执行我的DefaultSQLiteOpenhelper并创建所有数据库表,但它没有这样做:
public class DefaultSQLiteOpenHelper extends SQLiteOpenHelper implements ISQLiteOpenHelper
{
private static final String TAG = DefaultSQLiteOpenHelper.class.getSimpleName();
private static final String DATABASE_NAME = "MY_DATABASE";
private static final int DATABASE_VERSION = 1;
@Inject
public DefaultSQLiteOpenHelper(Context context)
{
super(context, DATABASE_NAME, null, DATABASE_VERSION);
}
//is called by the framework if the database doesn't exist
@Override
public void onCreate(SQLiteDatabase db)
{
Log.i(TAG, "no database found. Generating new database...");
createAllTables(db);
}
@Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion)
{
Log.w(TAG, "Upgrading database from version " + oldVersion + " to " + newVersion);
// db.execSQL("DROP TABLE IF EXISTS " + TABLE_COMMENTS); ///TODO when upgrade
// onCreate(db);
}
//The order must not be changed because sqlite doesn't allow
//table modification. That means one cannot add constraints afterwards
//which results in creating tables in a specific order
private final void createAllTables(SQLiteDatabase db)
{
db.beginTransaction();
//create lookups at first
db.execSQL(TableFactory.createUsage());
db.execSQL(TableFactory.createLanguage());
db.execSQL(TableFactory.createAccount());
db.execSQL(TableFactory.createPreferences());
db.execSQL(TableFactory.createLanguageUsageRel());
db.execSQL(TableFactory.createPantry());
db.execSQL(TableFactory.createProduct());
//populate lookups
db.execSQL(DataFactory.populateUsage());
db.execSQL(DataFactory.populateLanguage());
db.setTransactionSuccessful();
db.endTransaction();
db.close();
}
}
问题是,为什么它不打开一个数据库?文件上说必须这样做。我不接受任何肮脏的解决方法,比如手动打开数据库之类。我的代码到底出了什么问题?我不敢相信这是安卓系统的一个bug
以下是stacktrace:
05-27 17:25:50.370:I/DefaultSQLiteOpenHelper719:未找到数据库。
正在生成新数据库。。。05-27 17:25:50.400:W/dalvikvm719:
threadid=10:线程退出时未捕获异常组=0x40015560
05-27 17:25:50.400:E/AndroidRuntime719:致命异常:异步任务
1 05-27 17:25:50.400:E/AndroidRuntime719:java.lang.RuntimeException:执行时出错
doInBackground 05-27 17:25:50.400:E/AndroidRuntime719:at
android.os.AsyncTask$3.doneAsyncTask.java:200 05-27 17:25:50.400:
E/AndroidRuntime719:at
java.util.concurrent.FutureTask$Sync.innerSetExceptionFutureTask.java:274
05-27 17:25:50.400:E/AndroidRuntime719:at
java.util.concurrent.FutureTask.setExceptionFutureTask.java:125
05-27 17:25:50.400:E/AndroidRuntime719:at
java.util.concurrent.FutureTask$Sync.innerRunFutureTask.java:308
05-27 17:25:50.400:E/AndroidRuntime719:at
java.util.concurrent.FutureTask.runFutureTask.java:138 05-27
17:25:50.400:E/AndroidRuntime719:at
java.util.concurrent.ThreadPoolExecutor.runWorkerThreadPoolExecutor.java:1088
05-27 17:25:50.400:E/AndroidRuntime719:at
java.util.concurrent.ThreadPoolExecutor$Worker.runThreadPoolExecutor.java:581
05-27 17:25:50.400:E/AndroidRuntime719:at
java:1019 05-27 17:25:50.400:
E/AndroidRuntime719:原因:java.lang.IllegalStateException:
数据库未打开05-27 17:25:50.400:E/AndroidRuntime719:at
android.database.sqlite.SQLiteDatabase.endTransactionSQLiteDatabase.java:555
05-27 17:25:50.400:E/AndroidRuntime719:at
android.database.sqlite.SQLiteOpenHelper.getWritableDatabaseSQLiteOpenHelper.java:137
05-27 17:25:50.400:E/AndroidRuntime719:at
com.mydomain.android.base.persistence.PersistenceManager.loadAllPersistenceManager.java:58
05-27 17:25:50.400:E/AndroidRuntime719:at
com.mydomain.android.base.main.StartupTask.isFirstStartAfterInstallationStartupTask.java:107
05-27 17:25:50.400:E/AndroidRuntime719:at
com.mydomain.android.base.main.StartupTask.doInBackgroundStartupTask.java:52
05-27 17:25:50.400:E/AndroidRuntime719:at
com.mydomain.android.base.main.StartupTask.doInBackgroundStartupTask.java:18
05-27 17:25:50.400:E/AndroidRuntime719:at
android.os.AsyncTask$2.callAsyncTask.java:185 05-27 17:25:50.400:
E/AndroidRuntime719:at
java.util.concurrent.FutureTask$Sync.innerRunFutureTask.java:306
05-27 17:25:50.400:E/AndroidRuntime719:。。。4更多
首先,关闭createAllTables中的数据库。决不要从SQLiteOpenHelper的onCreate或onUpgrade关闭数据库 其次,在createAllTables中不需要事务逻辑,因为onCreate是在事务中执行的。这很好,因为无论如何,您的事务逻辑实现不正确 为了澄清后一种意见,正确的交易方式是:
try {
db.beginTransaction();
// SQL
db.setTransactionSuccessful();
}
// optional catch block
finally {
db.endTransaction();
}
如果存在SQL异常,则需要调用endTransaction—您的实现将跳过该异常。首先,您要关闭createAllTables中的数据库。决不要从SQLiteOpenHelper的onCreate或onUpgrade关闭数据库 其次,在createAllTables中不需要事务逻辑,因为onCreate是在事务中执行的。这很好,因为无论如何,您的事务逻辑实现不正确 为了澄清后一种意见,正确的交易方式是:
try {
db.beginTransaction();
// SQL
db.setTransactionSuccessful();
}
// optional catch block
finally {
db.endTransaction();
}
如果有SQL异常,则需要调用终结事务。您可能会考虑发布堆栈跟踪。@普通SWISE在这里是..dB.Calm在OnCuto中是不正确的。您可以考虑发布堆栈跟踪。@普通SWISE在这里是.dB.Calm在OnCuto中是不正确的。@AyncTask中的可写数据库?我很想说,它可能会导致并发异常。你能告诉我这个吗?@CommmonsWare T
汉克斯,真是个愚蠢的错误顺便问一下:您的意思是,对于未正确实现的情况,尽管在这个示例中我不需要它,但这是错误的事务处理方式吗?我在save方法中执行了类似的操作。@user2336315:允许在AyncTask中获取可写数据库吗?-它不仅是允许的,而且几乎是强制性的,因为如果必须创建或更新数据库,getWriteableDatabase可以执行重要的磁盘I/O。我很想说,它可能会导致并发异常正如您通过查看源代码所看到的,它同步了这项工作。@commonware谢谢,很高兴看到我已经在save方法中以这种方式完成了这项工作。@CommmonsWare允许在AyncTask中获取可写数据库吗?我很想说,它可能会导致并发异常。你能告诉我这个吗?@谢谢,这是个多么愚蠢的错误顺便问一下:您的意思是,对于未正确实现的情况,尽管在这个示例中我不需要它,但这是错误的事务处理方式吗?我在save方法中执行了类似的操作。@user2336315:允许在AyncTask中获取可写数据库吗?-它不仅是允许的,而且几乎是强制性的,因为如果必须创建或更新数据库,getWriteableDatabase可以执行重要的磁盘I/O。我很想说,它可能会导致并发异常正如您通过查看源代码所看到的,它同步了这项工作。@commonware谢谢,很高兴看到我已经在save方法中以这种方式完成了这项工作。