Android - SQLite 数据库

创建数据库

SQLiteOpenHelper 是一个抽象类,这意味着如果我们想要使用它的话, 就需要创建一个自己的帮助类去继承它。SQLiteOpenHelper 中有两个抽象方法,分别是 onCreate()和 onUpgrade(),我们必须在自己的帮助类里面重写这两个方法,然后分别在这两 个方法中去实现创建、升级数据库的逻辑。

SQLiteOpenHelper 中还有两个非常重要的实例方法,getReadableDatabase()和 getWritableDatabase()。这两个方法都可以创建或打开一个现有的数据库(如果数据库已存在 则直接打开,否则创建一个新的数据库),并返回一个可对数据库进行读写操作的对象。(如果数据库不存在,Android系统会自动生成一个数据库,接着调用onCreate()方法,onCreate()方法在初次生成数据库时才会被调用,在onCreate()方法里可以生成数据库表结构及添加一些应用使用到的初始化数据。如果数据库存在,不会调用onCreate()方法。)不同的是,当数据库不可写入的时候(如磁盘空间已满)getReadableDatabase()方法返回的对 象将以只读的方式去打开数据库,而 getWritableDatabase()方法则将出现异常。

SQLiteOpenHelper 中有两个构造方法可供重写,一般使用参数少一点的那个构造方法即 可。这个构造方法中接收四个参数,第一个参数是 Context,这个没什么好说的,必须要有 它才能对数据库进行操作。第二个参数是数据库名,创建数据库时使用的就是这里指定的名 称。第三个参数允许我们在查询数据的时候返回一个自定义的 Cursor,一般都是传入 null。 第四个参数表示当前数据库的版本号,可用于对数据库进行升级操作。

public class MyDatabaseHelper extends SQLiteOpenHelper {
        public static final String CREATE_BOOK = "create table book ("
                + "id integer primary key autoincrement, "
                + "author text, "
                + "price real, "
                + "pages integer, "
                + "name text)";
        private Context mContext;
        public MyDatabaseHelper(Context context, String name, CursorFactory
    factory, int version) {
            super(context, name, factory, version);
            mContext = context;
        }
        @Override
        public void onCreate(SQLiteDatabase db) {
            db.execSQL(CREATE_BOOK);
            Toast.makeText(mContext, "Create succeeded", Toast.LENGTH_SHORT).show(); }
        @Override
        public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) { }
}

SQLite 不像其他的数据库拥有众多繁杂的数据类型,它的数据类型很简单,integer 表示整型,real 表示浮点型,text 表示文本类型,blob 表示二进制类型。另外,上述建表语句中我们还 使用了 primary key 将 id 列设为主键,并用 autoincrement 关键字表示 id 列是自增长的。

    MyDatabaseHelper dbHelper = new MyDatabaseHelper(this, "BookStore.db", null, 1);
    dbHelper.getWritableDatabase();

升级数据库

当数据库需要增删数据表,或者修改表结构时就须要升级数据库(注意不是修改数据表中数据,而是数据表本身的变化)。

public class MyDatabaseHelper extends SQLiteOpenHelper {
        public static final String CREATE_BOOK = "create table Book ("
                + "id integer primary key autoincrement, "
                + "author text, "
                + "price real, "
                + "pages integer, "
                + "name text, "
                + "category_id integer)";
        public static final String CREATE_CATEGORY = "create table Category (" + "id integer primary key autoincrement, "
                + "category_name text, "
                + "category_code integer)";
        public MyDatabaseHelper(Context context, String name,
                CursorFactory factory, int version) {
            super(context, name, factory, version);
        }
        @Override
        public void onCreate(SQLiteDatabase db) {
            db.execSQL(CREATE_BOOK);
            db.execSQL(CREATE_CATEGORY);
            }
        @Override
        public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
            switch (oldVersion) {
            case 1:
                db.execSQL(CREATE_CATEGORY);
            case 2:
                db.execSQL("alter table Book add column category_id integer"); 
            default:
        } }
}

这里请注意一个非常重要的细节,switch 中每一个 case 的最后都是没有使用 break 的, 为什么要这么做呢?这是为了保证在跨版本升级的时候,每一次的数据库修改都能被全部执 行到。比如用户当前是从第二版程序升级到第三版程序的,那么 case 2 中的逻辑就会执行。 而如果用户是直接从第一版程序升级到第三版程序的,那么 case 1 和 case 2 中的逻辑都会执 行。使用这种方式来维护数据库的升级,不管版本怎样更新,都可以保证数据库的表结构是 最新的,而且表中的数据也完全不会丢失了。

添加数据

SQLiteDatabase 中提供了一个 insert()方法,这个方法就是专门用于添加数据的。它接收三个 参数,第一个参数是表名,我们希望向哪张表里添加数据,这里就传入该表的名字。第二个 参数用于在未指定添加数据的情况下给某些可为空的列自动赋值 NULL,一般我们用不到这 个功能,直接传入 null 即可。第三个参数是一个 ContentValues 对象,它提供了一系列的 put() 方法重载,用于向 ContentValues 中添加数据,只需要将表中的每个列名以及相应的待添加 数据传入即可。

public void onClick(View v) {
    SQLiteDatabase db = dbHelper.getWritableDatabase(); ContentValues values = new ContentValues();
    // 开始组装第一条数据
    values.put("name", "The Da Vinci Code"); 
    values.put("pages", 454);
    values.put("price", 16.96);
    db.insert("Book", null, values); 
    values.clear();
    // 开始组装第二条数据
    values.put("name", "The Lost Symbol"); 
    values.put("author", "Dan Brown"); 
    values.put("pages", 510);
    values.put("price", 19.95);
    db.insert("Book", null, values); 
    // 插入第二条数据
}

更新数据

SQLiteDatabase 中也是提供了一个非常好用的 update()方法用于对数据进行更新,这个方法 接收四个参数,第一个参数和 insert()方法一样,也是表名,在这里指定去更新哪张表里的数据。第二个参数是 ContentValues 对象,要把更新数据在这里组装进去。第三、第四个参数 用于去约束更新某一行或某几行中的数据,不指定的话默认就是更新所有行。

public void onClick(View v) {
                    SQLiteDatabase db = dbHelper.getWritableDatabase();
                    ContentValues values = new ContentValues(); 
                    values.put("price", 10.99);
                    db.update("Book", values, "name = ?", new String[] { "The Da Vinci Code" });
                    }

删除数据

SQLiteDatabase 中提供了一个 delete()方法专门用于删除数据,这个方法接收三个参数,第一 个参数仍然是表名,这个已经没什么好说的了,第二、第三个参数又是用于去约束删除某一 行或某几行的数据,不指定的话默认就是删除所有行。

public void onClick(View v) {
                    SQLiteDatabase db = dbHelper.getWritableDatabase();
                    db.delete("Book", "pages > ?", new String[] { "500" });
                }

查询数据

SQLiteDatabase 中还提供了一个 query()方法用于对数据进行查询。 这个方法的参数非常复杂,最短的一个方法重载也需要传入七个参数。那我们就先来看一下 这七个参数各自的含义吧,第一个参数不用说,当然还是表名,表示我们希望从哪张表中查 询数据。第二个参数用于指定去查询哪几列,如果不指定则默认查询所有列。第三、第四个 参数用于去约束查询某一行或某几行的数据,不指定则默认是查询所有行的数据。第五个参 数用于指定需要去 group by 的列,不指定则表示不对查询结果进行 group by 操作。第六个参 数用于对 group by 之后的数据进行进一步的过滤,不指定则表示不进行过滤。第七个参数用 于指定查询结果的排序方式,不指定则表示使用默认的排序方式。

public void onClick(View v) {
    SQLiteDatabase db = dbHelper.getWritableDatabase();
    // 查询Book表中所有的数据
    Cursor cursor = db.query("Book", null, null, null, null, null, null);
     if (cursor.moveToFirst()) {
        do {
            // 遍历Cursor对象,取出数据并打印
            String name = cursor.getString(cursor.getColumnIndex("name"));
            String author = cursor.getString(cursor.getColumnIndex("author"));
            int pages = cursor.getInt(cursor.getColumnIndex("pages"));
            double price = cursor.getDouble(cursor.getColumnIndex("price"));
             } while (cursor.moveToNext());
      }
     cursor.close();
}

使用事务

首先调用 SQLiteDatabase 的 beginTransaction() 方法来开启一个事务,然后在一个异常捕获的代码块中去执行具体的数据库操作,当所有的 操作都完成之后,调用 setTransactionSuccessful()表示事务已经执行成功了,最后在 finally 代码块中调用 endTransaction()来结束事务。注意观察,我们在删除旧数据的操作完成后手动 抛出了一个 NullPointerException,这样添加新数据的代码就执行不到了。不过由于事务的存 在,中途出现异常会导致事务的失败,此时旧数据应该是删除不掉的。

public void onClick(View v) {
    SQLiteDatabase db = dbHelper.getWritableDatabase(); 
    db.beginTransaction(); // 开启事务
    try {
        db.delete("Book", null, null);
        if (true) {
        // 在这里手动抛出一个异常,让事务失败
            throw new NullPointerException();
        }
        ContentValues values = new ContentValues(); 
        values.put("author", "George Martin"); 
        values.put("pages", 720);
        values.put("price", 20.85);
        db.insert("Book", null, values); 
        db.setTransactionSuccessful(); // 事务已经执行成功
        } 
    catch (Exception e) {
        e.printStackTrace();
    } finally {
        db.endTransaction(); // 结束事务
    } 
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值