当前位置: 代码迷 >> SQL >> Android开发之利用SQLite开展数据存储
  详细解决方案

Android开发之利用SQLite开展数据存储

热度:57   发布时间:2016-05-05 10:12:43.0
Android开发之利用SQLite进行数据存储

Android开发之利用SQLite进行数据存储

  • Android开发之利用SQLite进行数据存储
    • SQLite数据库简介
    • Android中如何使用SQLite
      • 1 创建SQLiteOpenHelper对象并创建表
      • 2 通过SQLiteDatabase对象执行增删改查操作
      • 3 SQLiteDatabase之事务transaction

1.SQLite数据库简介

SQLite,是一款轻型的数据库,是遵守ACID的关系型数据库管理系统,它包含在一个相对小的C库中。它是D.RichardHipp建立的公有领域项目。它的设计目标是嵌入式的,而且目前已经在很多嵌入式产品中使用了它,它占用资源非常的低,在嵌入式设备中,可能只需要几百K的内存就够了。它能够支持Windows/Linux/Unix等等主流的操作系统,同时能够跟很多程序语言相结合,比如 Tcl、C#、PHP、Java等,还有ODBC接口,同样比起M
ysql、PostgreSQL这两款开源的世界著名数据库管理系统来讲,它的处理速度比他们都快。SQLite第一个Alpha版本诞生于2000年5月。 至2015年已经有15个年头,SQLite也迎来了一个版本 SQLite 3已经发布。

总结 : SQLite作为移动终端的数据库是非常合适的,占用内存小轻量级处理速度快

2.Android中如何使用SQLite

2.1 创建SQLiteOpenHelper对象,并创建表

新建一个类,命名为MySQLiteOpenHelper,并将其继承自SQLiteOpenHelper:

新建后会报错,因为没有添加构造方法,添加构造方法:

    package com.example.sqllitetest;    import android.content.Context;    import android.database.sqlite.SQLiteDatabase;    import android.database.sqlite.SQLiteDatabase.CursorFactory;    import android.database.sqlite.SQLiteOpenHelper;    public class MySQLOpenHelper extends SQLiteOpenHelper {        public MySQLOpenHelper(Context context, String name, CursorFactory factory,                int version) {            super(context, name, factory, version);            // TODO Auto-generated constructor stub        }        /**         * 数据库创建时会调用,在这里执行创建表的语句         */        @Override        public void onCreate(SQLiteDatabase db) {            // TODO Auto-generated method stub        }        /**         * 数据库升级时,此方法会调用,在这里执行数据库更新操作         */        @Override        public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {            // TODO Auto-generated method stub        }        /**         * 数据库打开时,此方法会调用         */        @Override        public void onOpen(SQLiteDatabase db) {            // TODO Auto-generated method stub            super.onOpen(db);        }    }

在上面的onCreate();方法中执行一条创建表名为person的语句

    db.execSQL("create table person (_id integer primary key autoincrement, name char(10), age integer(3), phone integer(20))");

注意:其实在sqlite中除了id主键以外,所有的字段都没有明确的类型限制,举个列子,我们向integer类型的字段中插入char类型的数据也是可以的

那么既然这样,我们创建数据库时,指定的数据类型意图何在?

这些是为了,让我们程序员了解某个字段的类型限制,实际编码时,还是要指定字段明确类型的,方便日后维护和理解。

新建一个测试类SqliteTestCase.java:

    package com.example.sqllitetest;    import android.content.ContentValues;    import android.database.Cursor;    import android.database.sqlite.SQLiteDatabase;    import android.test.AndroidTestCase;    public class SqlliteTestCase extends AndroidTestCase {        private MySQLOpenHelper oh;        private SQLiteDatabase db;        public void test() {            System.out.println("This is test method!");        }        /**         * 测试框架初始化完毕过后,在测试方法调用之前调用此方法         */        @Override        protected void setUp() throws Exception {            super.setUp();            // 获得可写的数据库对象(若数据库不存在,先创建数据库,再获取可读可写的数据库对象;如果数据库存在,就直接打开)            // *********************** 参数说明 ***********************            // 参数1 : 获取Context对象,AndroidTestCase中为了方便测试,提供了getContext()方法            // 参数2 : 数据库文件名            // 参数3 : 游标工厂对象,被用来创建游标对象,默认为空            // 参数4 : 用来标识数据库的版本,用来与之前创建的时候做对比,当版本大于,则调用onUpgrade()            oh = new MySQLOpenHelper(getContext(), "person.db", null, 1);            /**             * ************** 第一种方法:获取数据库 **************             *  1.被用来创建或打开一个可读写的数据库,             *  当它被第一次调用的时候,会根据new SQLOpenHelper()中的数据库名和版本号             *  当已存在相同数据库文件,并且版本号相同,则直接打开,             *  反之,则调用创建或更新方法。             *               *  2.数据一旦打开成功,将被缓存起来,当我们在需要录入数据时,可以在任何地方去调用返回             *  的对象去操作数据库,注意:但不需要使用数据库时,需要关闭数据库             *               *  3.但没有权限时,抑或磁盘满了的时候,这个方法将会被调用失败,但是,若问题得到解决,即可成功调用             *               *  4.调用这个方法,若触发更新操作,你就需要警觉了:             *  因为数据库的更新是个耗时的操作,我们不应该在应用的主线程中去调用它,包括ContentProvider.onCreate()             *               */            db = oh.getWritableDatabase();            /**             * ************** 第二种方法:获取数据库 **************             * 不要被名字误导,这个方法同样可获得可读写的数据库对象,             * 它与上面方法的区别是,当遇到一些问题:(列如:磁盘满了,这个时候调用不会失败,而是将会返回一个只读的数据库对象)             */            db = oh.getReadableDatabase();        }        /**         * 测试方法执行完毕过后,调用此方法         */        @Override        protected void tearDown() throws Exception {            // TODO Auto-generated method stub            super.tearDown();            // 关闭数据库            db.close();        }    }

注意:当我们new SQLiteOpenHelper()打开某个数据库时,传入的版本号不应比之前创建这个数据库的时候绑定的版本号低,否则会出现下面的错误,版本号只能递增

运行test()方法,显示为绿色,说明没有错误

通过DDMS–>File Explore,查看data/data/项目包名/databases目录下:

导出文件,在SQLite Expert软件中打开:

可以看到,数据库和表都被正确创建。

2.2 通过SQLiteDatabase对象执行增删改查操作

2.2.1添加数据操作

添加数据有两种方法:

  • 第一种方法 : 通过手写sql语句,执行execSQL();方法;

在SqliteTestCase.java中添加insert()方法

 public void insert() {            db.execSQL("insert into person (name, age, phone) values(?, ? , ?)", new Object[]{"张三", 18, "180199678455"});            db.execSQL("insert into person (name, age, phone) values(?, ? , ?)", new Object[]{"赵四", 16, "180199678455"});            db.execSQL("insert into person (name, age, phone) values(?, ? , ?)", new Object[]{"Android", 15, "180199678455"});        }

执行结果,数据成功插入表中:

  • 第二种方法 : 通过Android API,将数据封装到contentValues中;

在SqliteTestCase.java中添加insertByApi()方法:

public void insertApi() {        // 把所有的数据封装到contentValues中        ContentValues values = new ContentValues();        values.put("name", "zhangsan");        values.put("age", 78);        values.put("phone", "13812235689");        // 参数说明:        // 第一个参数table             : 表名        // 第二个参数nullColumnHack :可以指定为null,若为null,当你values中无值,则不会插入行        //                             若你指定了nullColumnHack的值,即便你的values中无值,也会        //                            插入null值到你的字段下        // 第三个参数values            : ContentValues对象        db.insert("person", null, values);    }

导出db文件,刷新:

2.2.1删除数据操作

删除数据同样有两种方法:

  • 第一种方法 : 通过手写sql语句,执行execSQL();方法;
 public void delete() {            // 删除id为1的行            db.execSQL("delete from person where _id = ?", new Object[]{1});        }
  • 第二种方法 : 通过Android API;
public void deleteApi() {            // 删除表中age = 78, id = 4的记录            // 返回值为受影响的行,删除了多少行            int i = db.delete("person", "age = ? and _id = ?", new String[]{"78", "4"});        }

2.2.1修改数据操作

修改数据同样有两种方法:

  • 第一种方法 : 通过手写sql语句,执行execSQL()方法:
public void update() {            // 修改id为2的phone值为110            db.execSQL("update person set phone = ? where _id = ?", new Object[]{"110", 2});        }

查看结果:

  • 第二种方法 : 通过Android API;
public void updateApi() {            // 通过ContentValues来指定修改后的值            ContentValues values = new ContentValues();            values.put("phone", "120");            // 返回值为受影响的行            int i = db.update("person", values, "_id = ? and age = ?", new String[]{"3", "15"});        }

查看结果:

2.2.1查询数据操作

查询数据同样有两种方法:

  • 第一种方法 : rawQuery()方法:
public void query() {            Cursor cursor = db.rawQuery("select name, age, phone from person ", null);            while (cursor.moveToNext()) {                // 不推荐用这种下标的方式来获取值,一旦后期字段的位置有所改动,维护起来比较麻烦                // String name = cursor.getString(0);                // int age = cursor.getInt(1);                // String phone = cursor.getString(2);                // 推荐使用                String name = cursor.getString(cursor.getColumnIndex("name"));                int age = cursor.getInt(cursor.getColumnIndex("age"));                String phone = cursor.getString(cursor.getColumnIndex("phone"));                System.out.println("name : " + name + "; age = " + age + ";" + " phone = " + phone);            }        }

logcat输出结果:

  • 第二种方法 : 通过Android API;
public void queryApi() {            Cursor cursor = db.query("person", null, null, null, null, null, null);            while (cursor.moveToNext()) {                String name = cursor.getString(cursor.getColumnIndex("name"));                int age = cursor.getInt(cursor.getColumnIndex("age"));                String phone = cursor.getString(cursor.getColumnIndex("phone"));                System.out.println("name : " + name + "; age = " + age + ";" + " phone = " + phone);            }        }

2.3 SQLiteDatabase之事务transaction

应用场景:当需要保证多条语句同时执行成功,否则,回滚

这里,我们简单的模拟一下,假设我们需要id为2的age加1岁,同时又要保证id为3的age减1岁

原本数据在数据库中是这样:

如果事务执行成功后,name为赵四的age将变为17,而name为Android的age变为14,反之,两条数据的所有属性值不变。

首先,我们人为的导致执行失败:

添加方法:

public void transaction() {            try {                // 开启事务                db.beginTransaction();                ContentValues values = new ContentValues();                values.put("age", 17);                db.update("person", values, "_id = ?", new String[]{"2"});                values.clear();                values.put("age", 14);                db.update("person", values, "_id = ?", new String[]{"3"});                int i = 1 / 0; // 这里有错,将导致事务执行失败                // 设置事务执行成功                db.setTransactionSuccessful();            } catch (Exception e) {                // TODO: handle exception            } finally {                // 结束事务,同时提交,如果已经设置事务执行成功,则sql语句生效,反之,则回滚                db.endTransaction();            }        }

导出db文件,刷新,看到数据无任何变化:

再将错误去掉,执行方法:

结果如下,执行成功:

版权声明:本文为博主原创文章,未经博主允许不得转载。

  相关解决方案