2011-08-23 62 views
0

我已经将这个问题发布到android-developer邮件列表中,但没有任何成功。所以让我们试试:)Android SQLite不使用SQLiteOpenHelper创建表格

我想在这里实现的是非常简单的。使用SQLiteOpenHelper的子类,我试图创建一个全新的数据库(如果它不存在),所以我依赖于该类公开的onCreate()-方法。 这里是我的代码:

public class CurrencyStorageHelper extends SQLiteOpenHelper { 

private static final String TAG = "CurrencyStorageHelper"; 
private static final int DATABASE_VERSION = 1; 

public static final String DATABASE_NAME = "easycurrencyconverter.db"; 
public static final String COL_ID = "_id"; 

public static final String COL_CURRENCY_CODE = "currency_code"; 
public static final String COL_CURRENCY_VALUE = "currency_value"; 
public static final String COL_LAST_UPDATE = "last_update"; 
public static final String COL_LAST_DOWNLOADED = "last_downloaded"; 
public static final String COL_IS_TARGET_CURRENCY = "is_target_currency"; 
public static final String COL_CURRENCY_POSITION = "position"; 

public static final String TABLE_DEFAULT_CURRENCIES = "defaultcurrencies"; 
public static final String TABLE_CURRENCIES = "currencyhistory"; 
public static final String TABLE_CURRENCY_DEFINITION = "currencydefinition"; 

public static final String COL_DEFINITION_CODE = "code"; 
public static final String COL_DEFINITION_FULL_NAME = "full_name"; 




private static final String DATABASE_CREATE_1 = 
      "CREATE TABLE " + TABLE_CURRENCIES + " (" + COL_ID + " INTEGER PRIMARY KEY AUTOINCREMENT " + 
            ", " + COL_CURRENCY_CODE + " TEXT NOT NULL" + 
            ", " + COL_CURRENCY_VALUE + " REAL NOT NULL" + 
            ", " + COL_LAST_UPDATE + " REAL NOT NULL" + 
            ", " + COL_LAST_DOWNLOADED + " REAL NOT NULL); "; 
private static final String DATABASE_CREATE_2 = 
      "CREATE TABLE " + TABLE_DEFAULT_CURRENCIES + " (" + COL_ID + " INTEGER PRIMARY KEY AUTOINCREMENT " + 
            ", " + COL_CURRENCY_CODE + " TEXT NOT NULL" + 
            ", " + COL_CURRENCY_VALUE + " REAL NOT NULL" + 
            ", " + COL_CURRENCY_POSITION + " INTEGER NOT NULL" + 
            ", " + COL_LAST_UPDATE + " REAL NOT NULL" + 
            ", " + COL_LAST_DOWNLOADED + " REAL NOT NULL" + 
            ", " + COL_IS_TARGET_CURRENCY + " NUMERIC); "; 
private static final String DATABASE_CREATE_3 = 
      "CREATE TABLE " + TABLE_CURRENCY_DEFINITION + " (" + COL_ID + " INTEGER PRIMARY KEY AUTOINCREMENT " + 
            ", " + COL_DEFINITION_CODE + " TEXT NOT NULL" + 
            ", " + COL_DEFINITION_FULL_NAME + " TEXT NOT NULL); "; 


private static final String DATABASE_DROP = "DROP TABLE IF EXISTS " + TABLE_CURRENCIES + "; " + 
              "DROP TABLE IF EXISTS " + TABLE_DEFAULT_CURRENCIES + ";" + 
              "DROP TABLE IF EXISTS " + TABLE_CURRENCY_DEFINITION + ";"; 

public CurrencyStorageHelper(Context context) { 
    super(context, DATABASE_NAME, null, DATABASE_VERSION); 

} 

@Override 
public void onOpen(SQLiteDatabase db) { 
    super.onOpen(db); 
    Log.d(TAG, "Opening the database... " + db.getPath() + " version " + db.getVersion()); 
    db.setLockingEnabled(true); 
} 


@Override 
public void onCreate(SQLiteDatabase database) { 

    if (database.isDbLockedByCurrentThread()){ 
     Log.d(TAG, "Database locked by current thread..."); 
    } 


    if (database.isDbLockedByOtherThreads()){ 
     Log.e(TAG, "Database locked by OTHER thread..."); 
    } 

    if (database.isOpen()){ 
     Log.d(TAG, "OK.. Database open"); 
    } 

    if (database.isReadOnly()){ 
     Log.e(TAG, "The database is read only"); 
    } 

    if (database.inTransaction()){ 
     Log.e(TAG, "Why id the databse in transaction???"); 
    } 

    Log.d(TAG, "Call to onCreate"); 

    Log.d(TAG, "Creating table..." + DATABASE_CREATE_1); 

    database.beginTransaction(); 
    database.execSQL(DATABASE_CREATE_1); 
    database.endTransaction(); 

    Log.d(TAG, "Creating table..." + DATABASE_CREATE_2); 
    database.beginTransaction(); 
    database.execSQL(DATABASE_CREATE_2); 
    database.endTransaction(); 

    Log.d(TAG, "Creating table..." + DATABASE_CREATE_3);   
    database.beginTransaction(); 
    database.execSQL(DATABASE_CREATE_3); 
    database.endTransaction(); 
    insertInitialCurrencies(database); 
} 

/** 
* Create the default values to be shown to the user main activity when the application 
* is ran for the first time and no currencies have been downloaded yet. 
* @param database 
*/ 
private void insertInitialCurrencies(SQLiteDatabase database){ 

    int i = 1; 
    //TODO The fact that USD is the target currency is arbitrary. Maybe we should read user's 
    //locale to get her currency 
    insertDefaultCurrency(database, "USD", "U.S. Dollar", 1, i++, true, (new Date()).getTime(), (new Date()).getTime(), true, false); 
    insertDefaultCurrency(database, "EUR", "Euro", 1, i++, false, (new Date()).getTime(), (new Date()).getTime(), false, false); 
    insertDefaultCurrency(database, "GBP", "British Pound", 1, i++, false, (new Date()).getTime(), (new Date()).getTime(), false, false); 
    insertDefaultCurrency(database, "JPY", "Japanese Yen", 1, i++, false, (new Date()).getTime(), (new Date()).getTime(), false, false); 
    insertDefaultCurrency(database, "CNY", "Chinese Yuan", 1, i++, false, (new Date()).getTime(), (new Date()).getTime(), false, false); 
    insertDefaultCurrency(database, "CHF", "Swiss Franc", 1, i++, false, (new Date()).getTime(), (new Date()).getTime(), false, true); 


} 


    /** 
* Insert a new currency value which will be shown on the user main activity. 
* 
*/ 
private void insertDefaultCurrency(SQLiteDatabase database, 
          String currencyCode, 
          String currencyFullName, 
          double value, 
          int position, 
          boolean isTargetCurrency, 
          long lastModifiedDate, 
          long lastDownloadedDate, 
          boolean startTransaction, 
          boolean endTransaction){ 
    ContentValues vals = new ContentValues(); 
    vals.put(COL_CURRENCY_CODE, currencyCode); 
    vals.put(COL_CURRENCY_VALUE, value); 
    vals.put(COL_LAST_DOWNLOADED, lastDownloadedDate); 
    vals.put(COL_LAST_UPDATE, lastModifiedDate); 
    vals.put(COL_IS_TARGET_CURRENCY, (isTargetCurrency? 1 : 0)); 
    vals.put(COL_CURRENCY_POSITION, position); 

    if (startTransaction){ 
     database.beginTransaction(); 
    } 
    Log.d(TAG, "Adding default currency..." + currencyCode); 
    database.insertOrThrow(TABLE_DEFAULT_CURRENCIES, null, vals); 

    if (endTransaction){ 
     database.endTransaction(); 
    } 
} 

这里发生的事情是: 实际创建的数据库文件(大小3072个字节),但没有表获得创建,所以当我吃午饭的方法来查询DB我得到的异常

android.database.sqlite.SQLiteException: no such table. 

但是我没有得到任何SQL异常,所以我不知道为什么表没有被创建。

另外,每次运行我的应用程序时都会执行onCreate()-方法。数据库不存在时应该只执行一次吗?为什么它总是被称为?

调试我已经注意到了应用程序,打开后DB:

  1. getVersion()返回0
  2. isInTransaction()回报true
  3. SQLiteDatabase -instance设有私人属性mStackTrace 设置为DatabaseObjectNotClosedException,但我没有光标 尚未打开。

所有这些都发生在模拟器以及我的手机(三星Galaxy S2)上,所以我在这里错过了一些东西。

谢谢你可能给我的任何帮助/线索!

+0

'...但没有创建表。'您是否从您尝试插入时返回的错误消息得出这个结论,或者您是否为自己确认了这一结论?例如。你有没有试图针对(空)表发出一个选择? – Tim

+0

在数据库实际完成创建表的工作之前,代码执行是否可能贯穿插入语句? – Tim

+0

嗨添..我已经从/ data文件夹中拉出数据库文件,并打开一个SQLite管理软件和数据库确实是空的,这确认了为什么后来“我选择”执行失败。 –

回答

0

卸载您的应用程序并重新安装。

+0

我已经做了很多次..也检查了一旦应用程序已被卸载数据库实际上被删除。没有成功:( –

1

显然它现在工作。我已经提出了“提交”;在最后一个CREATE TABLE之后。 我不知道为什么我需要强制提交,但最终让我的代码工作。 但是查看日志我得到一个非阻塞例外:

08-23 15:45:17.714: ERROR/Database(18195): Failure 1 (cannot rollback - no transaction is active) on 0x1a3558 when executing 'ROLLBACK;' 

,但它不会阻止将要执行我的代码..现在。

谢谢大家!

Nico

2

您缺少setTransactionSuccessful()调用。请遵循以下模式:

db.beginTransaction(); 
    try { 
    ... 
    db.setTransactionSuccessful(); 
    } finally { 
    db.endTransaction(); 
    } 
+0

正如文档所述:(http:// developer .android.com /参考/机器人/数据库/源码/ SQLiteDatabase.html#的BeginTransaction%28%29) –

相关问题