Bur*_*jua 30 database android android-sqlite
我在我的应用程序中使用了包含多个表的数据库.我有一个XML解析器,需要在解析时将数据写入两个表.我为这两个表创建了两个数据库适配器,但现在我遇到了问题.当我使用一张桌子时,很容易:
FirstDBAdapter firstTable = new FirstDBAdapter(mycontext);
firstTable.open(); // open and close it every time I need to insert something
// may be hundreds of times while parsing
// it opens not a table but whole DB
firstTable.insertItem(Item);
firstTable.close();
Run Code Online (Sandbox Code Playgroud)
因为它是一个SAX解析器,在我看来(也许我错了),这将更好:
FirstDBAdapter firstTable = new FirstDBAdapter(mycontext);
@Override
public void startDocument() throws SAXException
{
firstTable.open(); // open and close only once
}
...
firstTable.insertItem(Item);
...
@Override
public void endDocument() throws SAXException
{
firstTable.close();
}
Run Code Online (Sandbox Code Playgroud)
但是,如果我需要将数据插入第二个表,我该怎么做?例如,如果我有第二个适配器,我认为这将是一个坏主意:
FirstDBAdapter firstTable = new FirstDBAdapter(mycontext);
SecondDBAdapter secondTable = new SecondDBAdapter(mycontext);
@Override
public void startDocument() throws SAXException
{
firstTable.open();
secondTable.open();
}
Run Code Online (Sandbox Code Playgroud)
有关如何实现这一点的任何想法?
小智 31
我已经成功创建了一个带有数据库名称/ create语句和其他共享信息的抽象基类,然后为每个表扩展它.这样,我可以将所有CRUD方法分开(我更喜欢).唯一的缺点是DATABASE_CREATE语句必须驻留在父类中,并且必须包含所有表,因为之后不能添加新表,但在我看来,保留CRUD的代价很小每个表的方法分开.
这样做很简单,但这里有一些注意事项:
这是我的抽象父类的代码,它基于Notepad Tutorial.孩子们只需要扩展它,调用super的构造函数(随意使用它):
package com.pheide.trainose;
import android.content.Context;
import android.database.SQLException;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteOpenHelper;
import android.util.Log;
public abstract class AbstractDbAdapter {
protected static final String TAG = "TrainOseDbAdapter";
protected DatabaseHelper mDbHelper;
protected SQLiteDatabase mDb;
protected static final String TABLE_CREATE_ROUTES =
"create table routes (_id integer primary key autoincrement, "
+ "source text not null, destination text not null);";
protected static final String TABLE_CREATE_TIMETABLES =
"create table timetables (_id integer primary key autoincrement, "
+ "route_id integer, depart text not null, arrive text not null, "
+ "train text not null);";
protected static final String DATABASE_NAME = "data";
protected static final int DATABASE_VERSION = 2;
protected final Context mCtx;
protected static class DatabaseHelper extends SQLiteOpenHelper {
DatabaseHelper(Context context) {
super(context, DATABASE_NAME, null, DATABASE_VERSION);
}
@Override
public void onCreate(SQLiteDatabase db) {
db.execSQL(TABLE_CREATE_ROUTES);
db.execSQL(TABLE_CREATE_TIMETABLES);
}
@Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
Log.w(TAG, "Upgrading database from version " + oldVersion + " to "
+ newVersion + ", which will destroy all old data");
db.execSQL("DROP TABLE IF EXISTS routes");
onCreate(db);
}
}
public AbstractDbAdapter(Context ctx) {
this.mCtx = ctx;
}
public AbstractDbAdapter open() throws SQLException {
mDbHelper = new DatabaseHelper(mCtx);
mDb = mDbHelper.getWritableDatabase();
return this;
}
public void close() {
mDbHelper.close();
}
}
Run Code Online (Sandbox Code Playgroud)
有关详细说明,请访问:http://pheide.com/page/11/tab/24#post13
War*_*ith 15
我的数据库适配器 实例始终存储在从Application继承的MyApplication中.想想第二个表,我定义了第一个表...目前这只是一个简短的版本,实际上这个适配器处理数据库中的7个表.
public class MyDbAdapter {
private static final String LOG_TAG = MyDbAdapter.class.getSimpleName();
private SQLiteDatabase mDb;
private static MyDatabaseManager mDbManager;
public MyDbAdapter() {
mDbManager = new MyDatabaseManager(MyApplication.getApplication());
mDb = mDbManager.getWritableDatabase();
}
public static final class GameColumns implements BaseColumns {
public static final String TABLE = "game";
public static final String IMEI = "imei";
public static final String LAST_UPDATE = "lastupdate";
public static final String NICKNAME = "nickname";
}
public String getImei() {
checkDbState();
String retValue = "";
Cursor c = mDb.rawQuery("SELECT imei FROM " + GameColumns.TABLE, null);
if (c.moveToFirst()) {
retValue = c.getString(c.getColumnIndex(GameColumns.IMEI));
}
c.close();
return retValue;
}
public void setImei(String imei) {
checkDbState();
ContentValues cv = new ContentValues();
cv.put(GameColumns.IMEI, imei);
mDb.update(GameColumns.TABLE, cv, null, null);
}
public boolean isOpen() {
return mDb != null && mDb.isOpen();
}
public void open() {
mDbManager = new MyDatabaseManager(MyApplication.getApplication());
if (!isOpen()) {
mDb = mDbManager.getWritableDatabase();
}
}
public void close() {
if (isOpen()) {
mDb.close();
mDb = null;
if (mDbManager != null) {
mDbManager.close();
mDbManager = null;
}
}
}
private void checkDbState() {
if (mDb == null || !mDb.isOpen()) {
throw new IllegalStateException("The database has not been opened");
}
}
private static class MyDatabaseManager extends SQLiteOpenHelper {
private static final String DATABASE_NAME = "dbname";
private static final int DATABASE_VERSION = 7;
private MyDatabaseManager(Context context) {
super(context, DATABASE_NAME, null, DATABASE_VERSION);
}
@Override
public void onCreate(SQLiteDatabase db) {
createGameTable(db);
}
@Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
Log.w(LOG_TAG, "Upgrading database from version " + oldVersion + " to " + newVersion + "!");
}
private void dropDatabase(SQLiteDatabase db) {
db.execSQL("DROP TABLE IF EXISTS " + GameColumns.TABLE);
}
private void createGameTable(SQLiteDatabase db) {
db.execSQL("CREATE TABLE " + GameColumns.TABLE + " ("
+ GameColumns._ID + " INTEGER PRIMARY KEY,"
+ GameColumns.IMEI + " TEXT,"
+ GameColumns.LAST_UPDATE + " TEXT,"
+ GameColumns.NICKNAME + " TEXT);");
ContentValues cv = new ContentValues();
cv.put(GameColumns.IMEI, "123456789012345");
cv.put(GameColumns.LAST_UPDATE, 0);
cv.put(GameColumns.NICKNAME, (String) null);
db.insert(GameColumns.TABLE, null, cv);
}
}
}
Run Code Online (Sandbox Code Playgroud)
mja*_*ama 10
phoxicle的解决方案是一个很好的起点,但根据Kevin Galligan 关于Android的SQLite序列化的说明,这个实现不是线程安全的,当多个数据库连接(例如来自不同线程)尝试编写数据库时,它将无声地失败:
如果您尝试同时从实际的不同连接写入数据库,则会失败.它不会等到第一个完成然后写.它根本不会写你的改变.更糟糕的是,如果您没有在SQLiteDatabase上调用正确版本的插入/更新,则不会出现异常.您只需在LogCat中收到一条消息即可.
那么,多线程?使用一个帮手.
这是一个使用静态SQLiteOpenHelper实例的phoxicle数据库适配器的修改实现,因此仅限于单个数据库连接:
public class DBBaseAdapter {
private static final String TAG = "DBBaseAdapter";
protected static final String DATABASE_NAME = "db.sqlite";
protected static final int DATABASE_VERSION = 1;
protected Context mContext;
protected static DatabaseHelper mDbHelper;
private static final String TABLE_CREATE_FOO =
"create table foo (_id integer primary key autoincrement, " +
"bar text not null)");
public DBBaseAdapter(Context context) {
mContext = context.getApplicationContext();
}
public SQLiteDatabase openDb() {
if (mDbHelper == null) {
mDbHelper = new DatabaseHelper(mContext);
}
return mDbHelper.getWritableDatabase();
}
public void closeDb() {
mDbHelper.close();
}
protected static class DatabaseHelper extends SQLiteOpenHelper {
public DatabaseHelper(Context context) {
super(context, DATABASE_NAME, null, DATABASE_VERSION);
}
@Override
public void onCreate(SQLiteDatabase db) {
db.execSQL(TABLE_CREATE_FOO);
}
@Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
Log.w(TAG, "Upgrading database from version " + oldVersion + " to " +
newVersion + ", which will destroy all old data");
db.execSQL("DROP TABLE IF EXISTS routes");
onCreate(db);
}
}
}
Run Code Online (Sandbox Code Playgroud)
为每个表扩展DBBaseAdapter以实现您的CRUD方法:
public class DBFooTable extends DBBaseAdapter {
public DBFooTable(Context context) {
super(context);
}
public void getBar() {
SQLiteDatabase db = openDb();
// ...
closeDb();
}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
33502 次 |
| 最近记录: |