我已将此问题发布到android-developer邮件列表中,但没有任何成功。所以我们试试吧:))
我想在这里实现的目标非常简单。使用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();
}
}
这里发生的事情是: 实际创建了db文件(调整大小为3072字节),但是没有创建表,所以当我午餐时查询数据库时我得到了异常
android.database.sqlite.SQLiteException: no such table.
但是我没有得到任何SQL异常,因此我不知道为什么不创建表。
此外,每次运行我的应用程序时都会执行onCreate()
- 方法。如果DB不存在,它应该只执行一次吗?为什么一直这么叫?
调试应用程序我注意到打开数据库之后:
getVersion()
返回0 isInTransaction()
返回true
SQLiteDatabase
- 实例具有私有属性mStackTrace
设置为DatabaseObjectNotClosedException
,但我没有光标
开了。这一切都发生在模拟器和我的手机(三星Galaxy S2)上,所以我在这里缺少一些东西。
感谢您提供给我的任何帮助/线索!!
答案 0 :(得分:2)
您缺少setTransactionSuccessful()调用。请遵循以下模式:
db.beginTransaction();
try {
...
db.setTransactionSuccessful();
} finally {
db.endTransaction();
}
答案 1 :(得分:1)
显然它现在正在运作。我放了一个“COMMIT;”在最后一个CREATE TABLE之后。 我不确定为什么我需要强制提交,但这最终让我的代码工作。 但是看着日志我得到了一个非阻塞异常:
08-23 15:45:17.714: ERROR/Database(18195): Failure 1 (cannot rollback - no transaction is active) on 0x1a3558 when executing 'ROLLBACK;'
但是现在还没有阻止我的代码被执行。
谢谢大家!!
尼科
答案 2 :(得分:0)
卸载您的应用程序并重新安装。
答案 3 :(得分:0)
看看openOrCreateDatabase方法。这可能更有意义覆盖,只是挂在它创建的代码部分。
http://developer.android.com/reference/android/database/sqlite/SQLiteDatabase.html