2013-05-27 2 views
1

Прежде всего, все подобные сообщения здесь не помогли.Почему SQLiteOpenHelper вызывает открытие базы данных IllegalArgumentException?

В AsyncTask Я проверяю, является ли запуск приложения самым первым запуском, это означает, что я проверяю наличие базы данных вообще. Я хочу сделать это по запросу из таблицы. Это то, что выполняется:

@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; 
} 

Аварии с IllegalArgumentException: база данных не открыта происходит на этой линии.

SQLiteDatabase db = defaultSQLiteOpenHelper.getWritableDatabase(); 

Это происходит именно на методе (см ниже) createAllTables.

The documentation говорит:

Создание и/или открыть базу данных, которая будет использоваться для чтения и письма. При первом вызове будет открыта база данных и onCreate (SQLiteDatabase), onUpgrade (SQLiteDatabase, int, int) и/или onOpen (SQLiteDatabase).

На мой взгляд, он должен выполнить свой 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(); 
    } 
} 

Вопрос в том, почему он не открыть базу данных? Документация говорит, что это необходимо. Я не принимаю никаких грязных решений в качестве решения, как открытие базы данных вручную или что-то в этом роде. Что именно не так в моем коде? Я не могу поверить, что это ошибка в Android.

Вот StackTrace:

05-27 17: 25: 50,370: I/DefaultSQLiteOpenHelper (719): база данных не найдено. Создание новой базы данных ... 05-27 17: 25: 50.400: W/dalvikvm (719): threadid = 10: нить, выходящая с неперехваченным исключением (группа = 0x40015560) 05-27 17: 25: 50.400: E/AndroidRuntime (719): неустранимый: AsyncTask

1 05-27 17: 25: 50,400: Е/AndroidRuntime (719): java.lang.RuntimeException: произошла ошибка при выполнении

doInBackground() 05- 27 17: 25: 50.400: E/AndroidRuntime (719): at android.os.AsyncTask $ 3.done (AsyncTask.java:200) 05-27 17: 25: 50.400: E/AndroidRuntime (719): at java.util.concurrent.FutureTask $ Sync.innerSetException (FutureTask.java:274) 05-27 17: 25: 50.400: E/AndroidRuntime (719): at java.util.concurrent.FutureTask.setException (FutureTask.java:125) 05-27 17: 25: 50.400: E/AndroidRuntime (719)): at java.util.concurrent.FutureTask $ Sync.innerRun (FutureTask.java:308) 05-27 17: 25: 50.400: E/AndroidRuntime (719): at java.util.concurrent.FutureTask.run (FutureTask.java:138) 05-27 17: 25: 50.400: E/AndroidRuntime (719): at java.util.concurrent.ThreadPoolExecutor.runWorker (ThreadPoolExecutor.java:1088) 05-27 17:25: 50.400: E/AndroidRuntime (719): at java.util.concurrent.ThreadPoolExecutor $ Worker.run (ThreadPoolExecutor.java:581) 05-27 17:25:50.400: E/AndroidRuntime (719): at java.lang.Thread.run (Thread.java:1019) 05-27 17: 25: 50.400: E/AndroidRuntime (719): вызвано: java.lang.IllegalStateException : база данных не открыта 05-27 17: 25: 50.400: E/AndroidRuntime (719): at android.database.sqlite.SQLiteDatabase.endTransaction (SQLiteDatabase.java:555) 05-27 17: 25: 50.400: E/AndroidRuntime (719): at android.database.sqlite.SQLiteOpenHelper.getWritableDatabase (SQLiteOpenHelper.java:137) 05-27 17: 25: 50.400: E/AndroidRuntime (719): at com.mydomain.android.base .persistence.PersistenceManager.loadAll (PersistenceManager.java:58) 05-27 17: 25: 50.400: E/AndroidRuntime (719): at com.mydomain.android.base.main.StartupTask.isFirstStartAfterI nstallation (StartupTask.java:107) 05-27 17: 25: 50.400: E/AndroidRuntime (719): at com.mydomain.android.base.main.StartupTask.doInBackground (StartupTask.java:52) 05- 27 17: 25: 50.400: E/AndroidRuntime (719): at com.mydomain.android.base.main.StartupTask.doInBackground (StartupTask.java:18) 05-27 17: 25: 50.400: E/AndroidRuntime (719): at android.os.AsyncTask $ 2.call (AsyncTask.java:185) 05-27 17: 25: 50.400: E/AndroidRuntime (719): at java.util.concurrent.FutureTask $ Sync.innerRun (FutureTask.java:306) 05-27 17: 25: 50.400: E/AndroidRuntime (719): ... 4 далее

+0

Вы можете рассмотреть возможность размещения трассировки стека. – CommonsWare

+0

@CommonsWare Вот оно. – Bevor

+1

'db.close()' in 'onCreate()' неверно. – laalto

ответ

5

Сначала вы закрываете базу данных в createAllTables(). Никогда не закрывайте базу данных от onCreate() или onUpgrade() от SQLiteOpenHelper.

Во-вторых, ваша транзакционная логика не нужна в createAllTables(), так как onCreate() выполняется в транзакции. Это хорошо, так как ваша логика транзакций неправильно реализована.

Чтобы уточнить, что последний комментарий, правильный способ сделать это сделки:

try { 
    db.beginTransaction(); 

    // SQL 

    db.setTransactionSuccessful(); 
} 
// optional catch block 
finally { 
    db.endTransaction(); 
} 

Вы должны endTransaction() называться, если есть исключение SQL - ваша реализация пропускает это.

+0

@CommmonsWare Дозволено ли получить загружаемую базу данных в AyncTask? У меня возникает соблазн сказать, что это может вызвать параллельное исключение. Не могли бы вы рассказать мне об этом, пожалуйста? – user2336315

+0

@CommmonsWare Спасибо, какая глупая ошибка. :) Кстати: Вы имеете в виду с неправильным внедрением, что это неправильный способ обработки транзакций (несмотря на этот пример, где он мне не нужен)? (Я делаю что-то подобное в моем методе сохранения). – Bevor

+2

@ user2336315: «Разрешено ли записывать базу данных в AyncTask?» - это не только разрешено, но и в значительной степени обязательным, так как 'getWriteableDatabase()' может выполнять значительные операции ввода-вывода на диске, если он должен создавать или обновлять базу данных. «У меня возникает соблазн сказать, что это может вызвать параллельное исключение». - как вы можете видеть, глядя на исходный код, он синхронизирует эту работу. – CommonsWare

Смежные вопросы