我已经将这个问题发布到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:
getVersion()
返回0- 的
isInTransaction()
回报true
- 的
SQLiteDatabase
-instance设有私人属性mStackTrace
设置为DatabaseObjectNotClosedException
,但我没有光标 尚未打开。
所有这些都发生在模拟器以及我的手机(三星Galaxy S2)上,所以我在这里错过了一些东西。
谢谢你可能给我的任何帮助/线索!
'...但没有创建表。'您是否从您尝试插入时返回的错误消息得出这个结论,或者您是否为自己确认了这一结论?例如。你有没有试图针对(空)表发出一个选择? – Tim
在数据库实际完成创建表的工作之前,代码执行是否可能贯穿插入语句? – Tim
嗨添..我已经从/ data文件夹中拉出数据库文件,并打开一个SQLite管理软件和数据库确实是空的,这确认了为什么后来“我选择”执行失败。 –