Android SQLite数据库使用小结

本文介绍如何使用SQLiteOpenHelper类创建和管理SQLite数据库。包括构造方法、获取数据库对象、基本的增删改查操作以及如何实现数据库的升级。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

基本用法

继承 SQLiteOpenHelper 类, 并实现重写构造方法:
public SQLiteOpenHelper(Context context, String name, CursorFactory factory, int version)

参数依次是: 上下文, 数据库名称呢个, 游标工厂, 数据库版本号.
使用该构造方法创建 helper 对象, 用于创建, 打开, 管理数据库. 创建或打开数据库需要调用下面两个方法中的一个.

SQLiteDatabase getWritableDatabase()
SQLiteDatabase getReadableDatabase()
重写 onCreate() 方法
void onCreate(SQLiteDatabase db);

这个方法会在数据库第一次被创建出来的时候调用. 一般在这里进行数据库表的初始化.

重写 onUpgrade() 方法
void onUpgrade(SQLiteDatabase db,int oldVersion,int newVersion);

这个方法会在数据库需要升级的时候调用. 可以在这个方法中添加或删除数据库表, 或者重命名表, 添加或删除数据列. 这个方法执行在事务内, 如果执行过程中出现了异常, 所有的改动都会自动回滚.

获取数据库对象

通过前面所列的两个方法 getWritableDatabase() 或 getReadableDatabase() 获取数据库对象SQLiteDatabase. 关于这两个方法的区别, 网上有一段描述:

getWritableDatabase() 方法以读写方式打开数据库,一旦数据库的磁盘空间满了,数据库就只能读而不能写,此时getWritableDatabase() 方法就会出错。 getReadableDatabase()方法则是先以读写方式打开数据库,如果数据库的磁盘空间满了,就会打开失败,当打开失败后会继续尝试以只读方式打开数据库。如果该问题成功解决,则只读数据库对象就会关闭

操作数据库中的数据

得到数据库对象(设对应变量名为 db)后就可以进行常规的数据库操作了, 有两种方式可以选择:

  1. 调用 db 的 execSQL()[增删改] 或 rawQuery()[查] 方法, 传入对应的 sql 语句来执行相关操作.
  2. 调用 db 中封装好的方法(insert, delete, update, query), 传入相应的参数来执行相关操作.

方法一使用sql语句, 比较灵活, 资源占用小, 可以实现表的级联查询. 方法二使用了现成的API, 比较方便, 可以避免sql语句拼写错误等, 不过看源码可以知道, 其内部还是将传入的参数拼装成sql语句后执行, 因此资源开销比较大. 不过方法二有返回值, 可以方便地知道是否执行成功.

具体实现方式如下:
sql语句( info 是表名 ):

  • 添加 insert into info (name,phone) values (‘zhangsan’,’110’)
  • 删除 delete from info where name=’zhangsan’
  • 修改 update info set phone =’999’ where name =’zhangsan’
  • 查询 select * from info where name=’zhangsan’

使用现有API

  • 添加:
ContentValues values = new ContentValues();
    values.put ("name",name);
    values.put("phone",phone);
    long result = db.insert("info", null, values);//成功返回新行行号,失败返回-1
  • 删除:
int db.delete(String table, String whereClause, String[] whereArgs)
  • 修改:
int update (table, values, whereClause, whereArgs)
  • 查询:
public Cursor query (String table, String[] columns, String selection, String[] selectionArgs, String groupBy, String having, String orderBy)
if(cursor.moveToNext()) phone = cursor.getString(0);

部分源码

SQLiteOpenHelper

public SQLiteDatabase getWritableDatabase() {
    synchronized (this) {
        return getDatabaseLocked(true);
    }
}
public SQLiteDatabase getReadableDatabase() {
    synchronized (this) {
        return getDatabaseLocked(false);
    }
}

可见两种获取数据库对象的方法都调用了同一个方法, 不过传递了不同的参数. 下面看看调用的这个方法:

private SQLiteDatabase getDatabaseLocked(boolean writable) {
    if (mDatabase != null) {
        if (!mDatabase.isOpen()) {
            // 用户调用了mDatabase.close().
            mDatabase = null;
        } else if (!writable || !mDatabase.isReadOnly()) {
            // 数据库已被打开.
            return mDatabase;
        }
    }

    if (mIsInitializing) {
        throw new IllegalStateException("getDatabase called recursively");
    }

    SQLiteDatabase db = mDatabase;
    try {
        mIsInitializing = true;

        if (db != null) {
            if (writable && db.isReadOnly()) {
                db.reopenReadWrite();
            }
        } else if (mName == null) {
        //mName是构造方法中传入的数据库的名称, 值为null时表示创建内存数据库,即应用关闭时数据库也会被清理
            db = SQLiteDatabase.create(null);
        } else {
            try {
                if (DEBUG_STRICT_READONLY && !writable) {
                    final String path = mContext.getDatabasePath(mName).getPath();
                    db = SQLiteDatabase.openDatabase(path, mFactory,
                            SQLiteDatabase.OPEN_READONLY, mErrorHandler);
                } else {
                    db = mContext.openOrCreateDatabase(mName, mEnableWriteAheadLogging ?
                            Context.MODE_ENABLE_WRITE_AHEAD_LOGGING : 0,
                            mFactory, mErrorHandler);
                }
            } catch (SQLiteException ex) {
                if (writable) {
                    throw ex;
                }
                Log.e(TAG, "Couldn't open " + mName
                        + " for writing (will try read-only):", ex);
                final String path = mContext.getDatabasePath(mName).getPath();
                db = SQLiteDatabase.openDatabase(path, mFactory,
                        SQLiteDatabase.OPEN_READONLY, mErrorHandler);
            }
        }

        onConfigure(db);
//获取当前数据库的版本号
        final int version = db.getVersion();
        if (version != mNewVersion) {
            if (db.isReadOnly()) {
                throw new SQLiteException("Can't upgrade read-only database from version " +
                        db.getVersion() + " to " + mNewVersion + ": " + mName);
            }

            db.beginTransaction();
            try {
                if (version == 0) {
                //说明数据库是第一次被创建, 调用onCreate()方法
                    onCreate(db);
                } else {
                    if (version > mNewVersion) {
                    //当前版本比较高的话, 调用降级方法
                        onDowngrade(db, version, mNewVersion);
                    } else {
                    //当前版本较低的话, 调用升级方法
                        onUpgrade(db, version, mNewVersion);
                    }
                }
                //更新当前数据库的版本号
                db.setVersion(mNewVersion);
                db.setTransactionSuccessful();
            } finally {
                db.endTransaction();
            }
        }

        onOpen(db);

        if (db.isReadOnly()) {
            Log.w(TAG, "Opened " + mName + " in read-only mode");
        }

        mDatabase = db;
        return db;
    } finally {
        mIsInitializing = false;
        if (db != null && db != mDatabase) {
            db.close();
        }
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值