android SQlite 详解

1.前言

 Sqlite是一款轻量级的关系型数据库,占用资源少,预算速度快,跨平台(支持android,IOS,window系统),弱类型(同一列中的数据可以是不同字段),非常适合资源较少的移动端开发。

2.数据库的创建

 (1)android提供了SQLiteOpenHelper这个帮助类实现数据库的创建和升级,SQLiteOpenHelpe是一个抽象类,必需实现这个类.

public class DbOpenHelper1 extends SQLiteOpenHelper {
    public DbOpenHelper1(Context context, String name, SQLiteDatabase.CursorFactory factory, int version) {
        super(context, name, factory, version);
    }

    @Override
    public void onCreate(SQLiteDatabase sqLiteDatabase) {

    }

    @Override
    public void onUpgrade(SQLiteDatabase sqLiteDatabase, int oldVersion, int newVersion) {

    }
}

SQLiteOpenHelper的构造方法的第二个参数(name)表示数据库名称,第四个参数(version)表示当前数据库的版本号。

 

SQLiteOpenHelper有两个重要方法onCreate和onUpgrade。

onCreate方法只有在创建数据库的时候会执行,所以一般在方法里实现表的创建。

onUpgrade方法实现数据库的升级。第二个oldVersion表示之前的数据库版本,newVersion表示当前版本。通过版本的不同可以实现数据库的升级

(2)在SQLiteOpenHelper的构造方法中传入的数据库名,其实数据库不是在这里创建。SQLiteOpenHelper提供了两个重要的方法getReadableDatabase和getWritableDatabase。

  调用SQLiteOpenHelper的这两个方法才会创建或者打开(已有)一个数据库,并返回SQLiteDatabase对象(数据库操作类,实现了操作数据库的一些方法)。

  下面是SQLiteDatabase的常用方法

SQLiteDatabase的常用方法 

方法名称
方法表示含义
openOrCreateDatabase(String path,SQLiteDatabase.CursorFactory  factory)
打开或创建数据库
insert(String table,String nullColumnHack,ContentValues  values)
插入一条记录
delete(String table,String whereClause,String[]  whereArgs)
删除一条记录
query(String table,String[] columns,String selection,String[]  selectionArgs,String groupBy,String having,String  orderBy)
查询一条记录
update(String table,ContentValues values,String whereClause,String[]  whereArgs)
修改记录
execSQL(String sql)
执行一条SQL语句
close()
关闭数据库

SQLiteDatabse是数据库操作的核心类。可以看到openOrCreateDatabase(path,factory)实现了打开或创建数据库。当调用SQLiteOpenHelper的getReadableDatabase和getWritableDatabase方法时,这两个方法的内部是通过调用SQLiteDatabase的openDatabase方法实现数据库的创建或打开的。看下这两个方法的源码。

SQLiteOpenHelper的源码:

185    public SQLiteDatabase More ...getReadableDatabase() {
186        synchronized (this) {
187            return getDatabaseLocked(false);
188        }
189    }


161    public SQLiteDatabase More ...getWritableDatabase() {
162        synchronized (this) {
163            return getDatabaseLocked(true);
164        }
165    }
他们都调用了getDatabaseLoced(boolen),看下这个方法的源码:

191    private SQLiteDatabase More ...getDatabaseLocked(boolean writable) {
192        if (mDatabase != null) {
193            if (!mDatabase.isOpen()) {
194                // Darn!  The user closed the database by calling mDatabase.close().
195                mDatabase = null;
196            } else if (!writable || !mDatabase.isReadOnly()) {
197                // The database is already open for business.
198                return mDatabase;
199            }
200        }
201
202        if (mIsInitializing) {
203            throw new IllegalStateException("getDatabase called recursively");
204        }
205
206        SQLiteDatabase db = mDatabase;
207        try {
208            mIsInitializing = true;
209
210            if (db != null) {
211                if (writable && db.isReadOnly()) {
212                    db.reopenReadWrite();
213                }
214            } else if (mName == null) {
215                db = SQLiteDatabase.create(null);
216            } else {
217                try {
218                    if (DEBUG_STRICT_READONLY && !writable) {
219                        final String path = mContext.getDatabasePath(mName).getPath();
220                        db = SQLiteDatabase.openDatabase(path, mFactory,
221                                SQLiteDatabase.OPEN_READONLY, mErrorHandler);
222                    } else {
223                        db = mContext.openOrCreateDatabase(mName, mEnableWriteAheadLogging ?
224                                Context.MODE_ENABLE_WRITE_AHEAD_LOGGING : 0,
225                                mFactory, mErrorHandler);
226                    }
227                } catch (SQLiteException ex) {
228                    if (writable) {
229                        throw ex;
230                    }
231                    Log.e(TAG, "Couldn't open " + mName
232                            + " for writing (will try read-only):", ex);
233                    final String path = mContext.getDatabasePath(mName).getPath();
234                    db = SQLiteDatabase.openDatabase(path, mFactory,
235                            SQLiteDatabase.OPEN_READONLY, mErrorHandler);
236                }
237            }
238
239            onConfigure(db);
240
241            final int version = db.getVersion();
242            if (version != mNewVersion) {
243                if (db.isReadOnly()) {
244                    throw new SQLiteException("Can't upgrade read-only database from version " +
245                            db.getVersion() + " to " + mNewVersion + ": " + mName);
246                }
247
248                db.beginTransaction();
249                try {
250                    if (version == 0) {
251                        onCreate(db);
252                    } else {
253                        if (version > mNewVersion) {
254                            onDowngrade(db, version, mNewVersion);
255                        } else {
256                            onUpgrade(db, version, mNewVersion);
257                        }
258                    }
259                    db.setVersion(mNewVersion);
260                    db.setTransactionSuccessful();
261                } finally {
262                    db.endTransaction();
263                }
264            }
265
266            onOpen(db);
267
268            if (db.isReadOnly()) {
269                Log.w(TAG, "Opened " + mName + " in read-only mode");
270            }
271
272            mDatabase = db;
273            return db;
274        } finally {
275            mIsInitializing = false;
276            if (db != null && db != mDatabase) {
277                db.close();
278            }
279        }
280    }

代码的218—225行,当数据库是可读状态时,调用了SQLiteDatabase.openDatabase)方法创建一个SQLiteDatabse。可写时通过Context的openOrCreateDatabase方法创建了SQLitedatabase,而该方法调用了SQLiteDatabase的openOrCreateDatabase。代码中的mName就是SQLiteOpenHelper传入的数据库名称。

看下SQLiteDatabase的源码:

714 
715     public static SQLiteDatabase More ...openOrCreateDatabase(String path, CursorFactory factory,
716             DatabaseErrorHandler errorHandler) {
717         return openDatabase(path, factory, CREATE_IF_NECESSARY, errorHandler);
718     }

可以看到openOrCreateDatabase其实也是调用了openDatabase这个方法。

691     public static SQLiteDatabase More ...openDatabase(String path, CursorFactory factory, int flags,
692             DatabaseErrorHandler errorHandler) {
693         SQLiteDatabase db = new SQLiteDatabase(path, flags, factory, errorHandler);
694         db.open();
695         return db;
696     }

在openDatabase方法中调用了SQLiteDatanase的构造函数,在SQLIteDatabse实现了数据库的创建,并返回SQLitedatabse这个数据库管理类。所以是通过SQLiteDatabase的openDatabase方法实现了数据库的创建,而openOrCreateDatabase调用了这个方法,也可以通过openOrCreateDatabase创建并打开一个数据库。

在看下SQLiteOpenHelper代码的第241—264行。version = db.getVersion()返回了当前数据库的版本,而mNewVersion) 这是在SQLiteOPenHelper传入的版本。当version 为0时,即创建数据库时调用onCreate(db);方法,而当version > mNewVersion时,当前版本大于新的版本时,调用了 onDowngrade(db, version, mNewVersion);这个可以实现数据库的回溯。当mNewVersion> Version调用了 onUpgrade(db, version, mNewVersion);实现数据库的升级。db.setVersion(mNewVersion);方法记入了新的版本号。

SQLiteDatabase不仅可以创建数据库,还实现了增删改查的基本SQL操作。提供了两种对数据的操作,一种是通过封装的方法insert,delete,query,update实现增删改查,还有一种通过execSQL执行sql语句。

3.封装

(1)可以看到不管是getReadableDatabase和getWritableDatabase方法调用getDatabaseLocked时都通过synchronized实现了数据库操作的锁,当创建SQLiteOpenHelper对象时可以通过单例模式实现数据库操作的同步。

SQLiteOpenHelper继承类。

public class DbOpenHelper extends SQLiteOpenHelper {
    private static DbOpenHelper instance;

    private static final String DATABSE_NAME = "student_manager";      //数据库名称
   // private static final int DATABASE_VERSION = 1;
   private static final int DATABASE_VERSION = 2;

    public static DbOpenHelper getInstance(Context context){
        if(instance == null){
            synchronized (DbOpenHelper.class){
                if(instance == null){
                    instance = new DbOpenHelper(context);
                }
            }
        }
        return instance;
    }

    /*
    学生表
     */
    private static final String STUDENT = "CREATE TABLE student"+
            "(student_id INTEGER PRIMARY KEY AUTOINCREMENT," +
            "name VARCHAR," +
            "sex VARCHAR)";

    /*
    成绩表
     */
    private static final String SUBJECT = "CREATE TABLE subject"+
            "(subject_id INTEGER PRIMARY KEY AUTOINCREMENT," +
            "sub_name VARCHAR," +
            "score FLOAT)";

    public DbOpenHelper(Context context) {
        super(context, DATABSE_NAME, null, DATABASE_VERSION);
    }

    @Override
    public void onCreate(SQLiteDatabase sqLiteDatabase) {             //创建数据库
        sqLiteDatabase.execSQL(STUDENT);               //创建学生表
        sqLiteDatabase.execSQL(SUBJECT);               //成績表
    }

    /*
     数据库表更新创建成绩表
     */
    @Override
    public void onUpgrade(SQLiteDatabase sqLiteDatabase, int oldVersion, int newVersion) {   //数据库表更新
        if(oldVersion < 2){
            sqLiteDatabase.execSQL(SUBJECT);
        }
    }
}

在onCreate方法中可以创建数据库时要创建的表,在onUpgrade方法中,当数据库要升级,可以创建新的表。
 创建了一个student_manager数据库,有两个表student和subject表。当数据库版本是1时创建了student(在onCreate)执行。当数据库版本为2时,增加了subject表(在onUpgrade)执行。

(2)表的操作

public class SqliteManager {
    private DbOpenHelper mOpenHelper;
    private SQLiteDatabase sqLiteDatabase;


    public void open(Context context){
        mOpenHelper = DbOpenHelper.getInstance(context);
        sqLiteDatabase = mOpenHelper.getWritableDatabase();
    }

    public void close(){
        mOpenHelper.close();
    }

    //---------------------------------学生表操作-------------------------------------
    public synchronized long insertStudent(String name,String sex){
        ContentValues contentValues = new ContentValues();
        contentValues.put("name",name);
        contentValues.put("sex",sex);
        return sqLiteDatabase.insert(SqliteUtil.student_table,null,contentValues);
    }


    public Cursor selectStudent(String name){
        Cursor cursor =  sqLiteDatabase.rawQuery("select * from student where name=?",new String[]{name});
        return  cursor;
    }

    public void updateStudent(String id,String name,String sex){
        ContentValues contentValues = new ContentValues();
        contentValues.put("name",name);
        contentValues.put("sex",sex);
        sqLiteDatabase.update(SqliteUtil.student_table,contentValues,"student_id=?",new String[]{id});
    }
}

(3)方法调用

    Student表中插入一条数据

 SqliteManager sqliteManager = new SqliteManager();
                sqliteManager.open(getApplicationContext());
                sqliteManager.insertStudent("张三","男");
                sqliteManager.close();

资源地址点击打开链接

   

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值