android数据存储之Sqlite(二)

SQLite学习笔记

前言:上一章我们介绍了sqlite的一些基本知识以及在dos命令下对sqlite进行的增删改查的操作,这一章我们将在android项目中实际来操作sqlite。

1、 SQLiteDatabase的介绍

Android提供了创建和是用SQLite数据库的API。SQLiteDatabase代表一个数据库对象,提供了操作数据库的一些方法。在 Android的SDK目录下有sqlite3工具,我们可以利用它创建数据库、创建表和执行一些SQL语句。下面是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()


关闭数据库

2、SQLiteOpenHelper

  该类是SQLiteDatabase一个辅助类。这个类主要生成一 个数据库,并对数据库的版本进行管理。当在程序当中调用这个类的方法getWritableDatabase()或者 getReadableDatabase()方法的时候,如果当时没有数据,那么Android系统就会自动生成一个数据库。 SQLiteOpenHelper 是一个抽象类,我们通常需要继承它,并且实现里面的3个函数:

1.onCreate(SQLiteDatabase)

在数据库第一次生成的时候会调用这个方法,也就是说,只有在创建数据库的时候才会调用,当然也有一些其它的情况,一般我们在这个方法里边生成数据库表。

2.  onUpgrade(SQLiteDatabase,int,int)

当数据库需要升级的时候,Android系统会主动的调用这个方法。一般我们在这个方法里边删除数据表,并建立新的数据表,当然是否还需要做其他的操作,完全取决于应用的需求。

3.  onOpen(SQLiteDatabase):

这是当打开数据库时的回调函数,一般在程序中不是很常使用。

写了这么多,改改用实际例子来说明上面的内容了。下面这个操作数据库的实例实现了创建数据库,创建表以及数据库的增删改查的操作。

3、 实例一,利用execSQL()rawQuery()方法来实现sqlite数据库的增删改查

程序中需要用到的模型层Student:

package com.demo.sqlite.model;

public class Student {

    private int sid;
    private String sname;
    private short age;

    public Student(int sid, String sname, short age) {
        super();
        this.sid = sid;
        this.sname = sname;
        this.age = age;
    }

    public Student() {
        super();
    }

    public int getSid() {
        return sid;
    }

    public void setSid(int sid) {
        this.sid = sid;
    }

    public String getSname() {
        return sname;
    }

    public void setSname(String sname) {
        this.sname = sname;
    }

    public short getAge() {
        return age;
    }

    public void setAge(short age) {
        this.age = age;
    }

    @Override
    public String toString() {
        return "sid:" + sid + ",sname:" + sname + ",age:" + age;
    }
}

(1)     编写一个类继承自SQLiteOpenHelper 

package com.demo.sqlite.dao;

import android.content.Context;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteOpenHelper;
import android.util.Log;

//sqlite中文社区:http://www.sqlite.com.cn/POPlist.asp?classid=5
public class DBOpenHelper extends SQLiteOpenHelper {

    // 数据库的版本
    private static final int VERSION = 1;
    // 数据库的名称
    private static final String DBNAME = "data.db";
    // 数据表名
    private static final String TABLE_NAME = "t_student";

    public DBOpenHelper(Context context) {
        super(context, DBNAME, null, VERSION);
    }

    // 数据第一次创建的时候执行
    @Override
    public void onCreate(SQLiteDatabase db) {
        // 创建数据库表
        // db.execSQL("create table t_student(sid integer,sname varchar(20),age integer)");
        db.execSQL("create table " + TABLE_NAME
                + " (sid integer,sname varchar(20),age integer)");

    }

    // 更新版本,更新数据(数据的备份)
    @Override
    public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
        Log.i("StudentDaoTest", "Upgrade");
        String tempstudent = "temp_student";
        // 修改t_student表为temp_student
        db.execSQL("alter table " + TABLE_NAME + " rename to " + tempstudent);
        // 创建t_student表
        db.execSQL("create table " + TABLE_NAME
                + " (sid integer,sname varchar(20),age integer,sex varchar(4))");
        // 查询temp_student表中的数据并插入到t_student表中
        String sql = "insert into " + TABLE_NAME
                + " (sid,sname,age,sex) select sid,sname,age,‘男‘ from " + tempstudent;
        db.execSQL(sql);
    }
}

(2)     业务逻辑层StudentDao的编写

package com.demo.sqlite.dao;

import java.util.ArrayList;
import java.util.List;

import com.demo.sqlite.model.Student;

import android.content.Context;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;

public class StudentDao {

    private DBOpenHelper helper;
    private SQLiteDatabase db;

    public StudentDao(Context context) {
        helper = new DBOpenHelper(context);
    }

    /**
     * 添加学生信息
     * @param stu
     */
    public void add(Student stu) {
        db = helper.getWritableDatabase();
        db.execSQL("insert into t_student(sid,sname,age) values(?,?,?)",
                new Object[] { stu.getSid(), stu.getSname(), stu.getAge() });
    }

    /**
     * 更新学生信息
     * @param stu
     */
    public void update(Student stu) {
        db = helper.getWritableDatabase();
        db.execSQL("update t_student set sname = ? ,age = ? where sid = ? ",
                new Object[] {stu.getSname(), stu.getAge() ,stu.getSid()});
    }

    /**
     * 根据sid查询学生信息
     * @param sid
     * @return
     */
    public Student findStudentById(int sid) {
        db = helper.getWritableDatabase();
        Cursor cursor = db.rawQuery(
                "select sid,sname,age from t_student where sid = ? ",
                new String[] { String.valueOf(sid) });
        if (cursor.moveToNext()) {
            return new Student(cursor.getInt(cursor.getColumnIndex("sid")),
                    cursor.getString(cursor.getColumnIndex("sname")),
                    cursor.getShort(cursor.getColumnIndex("age")));
        }
        return null;
    }

    /**
     * 根据sid删除学生信息
     * @param sid
     */
    public void delete(Integer... sids) {
        if (sids.length > 0) {
            StringBuffer sb = new StringBuffer();
            for (int i = 0; i < sids.length; i++) {
                sb.append("?").append(",");
            }
            sb.deleteCharAt(sb.length() - 1);
            db = helper.getWritableDatabase();
            db.execSQL("delete from t_student where sid in (" + sb + ")",
                    (Object[]) sids);
        }
    }

    /**
     * 查找学生信息
     * @param start    起始位置
     * @param count    学生数量
     * @return
     */
    public List<Student> getStudent(int start,int count){
        List<Student> students = new ArrayList<Student>();
        db = helper.getWritableDatabase();
        Cursor cursor = db.rawQuery("select sid,sname,age from t_student limit ?,? ",new String[]{String.valueOf(start),String.valueOf(count)});
        while(cursor.moveToNext()){
            students.add(new Student(cursor.getInt(cursor.getColumnIndex("sid")), cursor.getString(cursor.getColumnIndex("sname")), cursor.getShort(cursor.getColumnIndex("age"))));
        }
        return students;
    }

    /**
     * 获取学生数量
     * @return
     */
    public long getCount(){
        db = helper.getWritableDatabase();
        Cursor cursor = db.rawQuery("select count(sid) from t_student",null);
        if(cursor.moveToNext()){
            return cursor.getLong(0);
        }
        return 0;
    }
}

(3)  为了更快速的检测我们写的代码的正确性,我这里就不在使用Activity来展示并实行功能了,而是直接采用单元测试,这样更方便

    3-1)编写测试代码,在与src同级下建立一个test资源文件夹,接着建一个和android项目包名一致的包,我这里是com.demo.sqlite.activity,然后编写一个类继承AndroidTestCase,测试代码如下:

package com.demo.sqlite.activity;

import java.util.List;

import com.demo.sqlite.dao.StudentDao;
import com.demo.sqlite.model.Student;

import android.test.AndroidTestCase;
import android.util.Log;

/**
 * 单元测试
 * @author yinbenyang
 *
 */
public class StudentDaoTest extends AndroidTestCase {

    //日志输出
    private static final String TAG = "StudentDaoTest";

    //测试添加方法
    public void testAdd(){
        StudentDao sdao = new StudentDao(this.getContext());
        Student stu = new Student(1,"zhangsan",(short)23);
        sdao.add(stu);
        Log.i(TAG, "添加学生成功");
    }

    //测试修改方法
    public void testUpdate(){
        StudentDao sdao = new StudentDao(this.getContext());
        Student stu = sdao.findStudentById(1);
        stu.setSname("lisi");
        sdao.update(stu);
        Log.i(TAG, "修改学生信息成功");
    }

    //测试根据id查找学生方法
    public void testFindStudentById(){
        StudentDao sdao = new StudentDao(this.getContext());
        Student stu = sdao.findStudentById(1);
        if(stu == null){
            Log.i(TAG, "not find");
        }else{
            Log.i(TAG, stu.toString());
        }
    }

    //测试删除方法
    public void testDelete(){
        StudentDao sdao = new StudentDao(this.getContext());
        sdao.delete(1,2);
        Log.i(TAG, "删除成功");
    }

    //测试获取总人数的方法
    public void testGetCount(){
        StudentDao sdao = new StudentDao(this.getContext());
        long count = sdao.getCount();
        Log.i(TAG, count+"");
    }

    //测试分页方法
    public void testGetStudent(){
        StudentDao sdao = new StudentDao(this.getContext());
        List<Student> lists = sdao.getStudent(0, 1);
        for (Student s : lists) {
            Log.i(TAG, s.toString());
        }
    }
}

  3-2)在android的AndroidManifest.xml文件中进行单元测试的配置:

  <manifest xmlns:android="http://schemas.android.com/apk/res/android"
      package="com.demo.sqlite.activity"
      android:versionCode="1"
      android:versionName="1.0" >

<uses-sdk
        android:minSdkVersion="15"
        android:targetSdkVersion="15" />

<application
        android:allowBackup="true"
        android:icon="@drawable/ic_launcher"
        android:label="@string/app_name"
        android:theme="@style/AppTheme" >
        <uses-library android:name="android.test.runner" />
    </application>

<instrumentation
        android:name="android.test.InstrumentationTestRunner"
        android:targetPackage="com.demo.sqlite.activity"
        android:label="Test My App" >
    </instrumentation>
</manifest>

------------------------------------------------------------------分割线-----------------------------------------------------------------------------------------

实例二,利用SqliteDatabase自带的insert(),delete(),update(),query()进行增删改查的操作

(1)编写一个类继承自SQLiteOpenHelper,同上,不在赘述

(2)业务逻辑层StudentDao2的编写:

package com.demo.sqlite.dao;

import java.util.ArrayList;
import java.util.List;

import com.demo.sqlite.model.Student;

import android.content.ContentValues;
import android.content.Context;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;

public class StudentDao2 {

    private DBOpenHelper helper;
    private SQLiteDatabase db;

    public StudentDao2(Context context) {
        helper = new DBOpenHelper(context);
    }

    /**
     * 添加学生信息
     * @param stu
     */
    public void add(Student stu) {
        db = helper.getWritableDatabase();
        ContentValues values = new ContentValues();
        values.put("sid", stu.getSid());
        values.put("sname", stu.getSname());
        values.put("age", stu.getAge());
        /**
         * 第一个参数:String table:插入数据的数据表名
         * 第二个参数:String nullColumnHack:当values参数为空或者里面没有内容的时候,insert是会失败的(不允许插入空行),
         *         为了防止这种情况,我们指定一个列名,如果发现要插入的行为空行时,就会将你设定的列名的值设为null,然后在向数据库表中插入,
         *         例如当values为空时,实际上sql语句变成了:insert into t_student(sid) values(null);
         * 第三个参数:ContentValues values:一个ContentValues对象,类似于map
         */
        db.insert("t_student", "sid", values);
    }

    /**
     * 更新学生信息
     * @param stu
     */
    public void update(Student stu) {
        db = helper.getWritableDatabase();
        ContentValues values = new ContentValues();
        values.put("sname", stu.getSname());
        values.put("age", stu.getAge());
        db.update("t_student", values, " sid = ? ", new String[]{String.valueOf(stu.getSid())});
    }

    /**
     * 根据sid查询学生信息
     * @param sid
     * @return
     */
    public Student findStudentById(int sid) {
        db = helper.getWritableDatabase();
        Cursor cursor =  db.query("t_student", new String[]{"sid","sname","age"},"sid = ? " ,new String[]{String.valueOf(sid)},"","","");
        if(cursor.moveToNext()){
            //这里使用0,1,2是根据各自在t_student表中的位置来定位的,也可以使用cursor.getInt(cursor.getColumnIndex("sid"))
            return new Student(cursor.getInt(0), cursor.getString(1),cursor.getShort(2));
        }
        return null;
    }

    /**
     * 根据sid删除学生信息
     * @param sid
     */
    public void delete(Integer... sids) {
        if (sids.length > 0) {
            StringBuffer sb = new StringBuffer();
            String[] strSid = new String[sids.length];
            for (int i = 0; i < sids.length; i++) {
                sb.append("?").append(",");
                strSid[i] = String.valueOf(sids[i]);
            }
            sb.deleteCharAt(sb.length() - 1);
            db = helper.getWritableDatabase();
            db.delete("t_student", "sid in("+sb+")", strSid);
        }
    }

    /**
     * 查找学生信息
     * @param start    起始位置
     * @param count    学生数量
     * @return
     */
    public List<Student> getStudent(int start,int count){
        List<Student> students = new ArrayList<Student>();
        db = helper.getWritableDatabase();
        /** query()方法中各参数的说明
         *  ①table:表名称
                  ②columns:列名称数组
            ③selection:条件字句,相当于where
            ④selectionArgs:条件字句,参数数组
            ⑤groupBy:分组列
            ⑥having:分组条件
            ⑦orderBy:排序列
            ⑧limit:分页查询限制
         */
        Cursor cursor = db.query("t_student", new String[]{"sid","sname","age"}, null, null, null, null, "sid desc",start+","+count);
        while(cursor.moveToNext()){
            students.add(new Student(cursor.getInt(0), cursor.getString(1), cursor.getShort(2)));
        }
        return students;
    }

    /**
     * 获取学生数量
     * @return
     */
    public long getCount(){
        db = helper.getWritableDatabase();
        Cursor cursor = db.query("t_student", new String[]{"count(*)"}, null, null, null, null, null);
        if(cursor.moveToNext()){
            return cursor.getLong(0);
        }
        return 0;
    }
}

(3) 单元测试类的编写,和上面第一种实例的差不多,就是将StudentDao换成StudentDao2,此处不在赘述。

4、 运行测试

  (1)测试添加方法testAdd(),点击项目名-->test-->包名-->StudentDaoTest-->testAdd(),右键run as,选择Android JUnit Test,如图

接着我们在测试查询的结果,如图:

生成的data.db存放在data/data/项目包名/dataases/data.db中。可以通过ddms视图看到,也可以在dos下使用命令来查看:

(2)在上面的DBOpenHelper 这个类里面有一个onUpgrade()方法,这个是用来更新数据库版本的操作的,当数据库版本有改变时,将会执行这个方法,例如现在将DBOpenHelper 里面的VERSION改为2,在运行测试testFindStudentById()方法会出现什么情况呢?如下图:

这时我们看到onUpgrade里面的log日志打印出来了,并且执行了里面的操作【向t_student表中添加一个sex字段,实现的思路是:先将t_student表重命名为temp_student,然后重新创建一个带有sex字段的表,接着查询出temp_student表中的数据并插入到t_student表中,也就是说此时的data.db中有两张表:t_student和temp_student,t_student表中有四个四段,而temp_studnet表中只有三个字段】,使用命令来查看效果:

时间: 2024-10-27 07:15:15

android数据存储之Sqlite(二)的相关文章

Android数据存储之SQLite的操作

Android作为一个应用在移动设备上的操作系统,自然也就少不了数据的存储.然而SQLite作为一个轻型的关系型数据库,基于其轻量.跨平台.多语言接口及安全性等诸多因数考虑,因而Android较大的数据存储采用了SQLite.SQLite与大多数关系型数据库一样都遵循ACID,语法也非常相似.只要您懂得mysql.sqlserver等关系型数据库的操作,只要查看下SQLite的官方文档便可快速上手.SQLite语法您可通过http://sqlite.org/lang.html进行查看. 接下来看

【转载】Android数据存储之SQLite

SQLite是D.Richard Hipp用C语言编写的开源嵌入式数据库引擎.它支持大多数的SQL92标准,并且可以在所有主要的操作系统上运行. 在Android中创建的SQLite数据库存储在:/data/data/<包名>/databases/目录下. 主要特点: -轻量级 -独立性,没有不依赖,无需安装 -跨平台,支持众多操作系统 -支持高达2TB大小的数据库 -每个数据库以单个文件的形式存在 -以B-Tree的数据结构形式存储在硬盘 SQLite的数据类型: SQLite支持NULL.

Android数据存储之SQLite使用

SQLite是D.Richard Hipp用C语言编写的开源嵌入式数据库引擎.它支持大多数的SQL92标准,并且可以在所有主要的操作系统上运行. 在Android中创建的SQLite数据库存储在:/data/data/<包名>/databases/目录下. 主要特点: -轻量级 -独立性,没有不依赖,无需安装 -跨平台,支持众多操作系统 -支持高达2TB大小的数据库 -每个数据库以单个文件的形式存在 -以B-Tree的数据结构形式存储在硬盘 SQLite的数据类型: SQLite支持NULL.

Android数据存储之SQLite数据库

SQLite是一个小巧的嵌入式数据库,使用方便.开发简单,手机上最早由IOS运用,后来Android也采用了SQLite. SQLite的多数SQL语法与Oracle 一样,下面只列出不同的地方: (1)建表时为避免重复操作,应加上IF NOT EXISTS关键词,例如CREATE TABLE IF NOT EXISTS table_name (2)删表时为避免重复操作,应加上IF EXISTS关键词,例如DROP TABLE IF EXISTS table_name (3)添加新列时使用ALT

android数据存储之Sqlite(一)

SQLite学习笔记 1. Sqlite简介 SQLite是一款轻型的数据库,是遵守ACID的关联式数据库管理系统,它的设计目标是嵌入 式的,而且目前已经在很多嵌入式产品中使用了它,它占用资源非常的低,在嵌入式设备中,可能只需要几百K的内存就够了.它能够支持 Windows/Linux/Unix等等主流的操作系统,同时能够跟很多程序语言相结合,比如Tcl.PHP.Java.C++..Net等,还有 ODBC接口,同样比起 Mysql.PostgreSQL这两款开源世界著名的数据库管理系统来讲,它

Android数据存储之Sqlite采用SQLCipher数据库加密实战

前言: 最近研究了Android Sqlite数据库(文章地址:http://www.cnblogs.com/whoislcj/p/5506294.html)以及ContentProvider程序间数据共享(http://www.cnblogs.com/whoislcj/p/5507928.html),我们清晰的知道Sqlite数据库默认存放位置data/data/pakage/database目录下,对于已经ROOT的手机来说的没有任何安全性可以,一旦被利用将会导致数据库数据的泄漏,所以我们该

android 数据存储之SQLite

使用嵌入式关系型SQLite数据库存储数据 除了可以使用文件或SharedPreferences存储数据,还可以选择使用SQLite数据库存储数据. 在Android平台上,集成了一个嵌入式关系型数据库—SQLite, 1.SQLite3支持 NULL.INTEGER.REAL(浮点数字).TEXT(字符串文本)和BLOB(二进制对象)数据类型,虽然它支持的类型虽然只有五种,但实际上sqlite3也接受varchar(n).char(n).decimal(p,s) 等数据类型,只不过在运算或保存

Android数据存储引擎---SQLite数据库

目标:是否可以在PC端桌面上使用SQLite数据库制作一个财务文件? 目录: 来源: 实践: 总结和比较: SQLite数据简介 是什么,内部结构是怎样的,数据库和表的关系是什么 有什么用 常用的操作是什么 SQLite数据库使用 增 删 改 查 SQLite数据库实践上的优化措施 对于Android平台来说,系统内置了丰富的API来供开发人员操作SQLite,使我们轻松完成对数据的存取. 步骤1,熟悉创建数据库表,熟悉相关的操作指令,实现对SQLite数据库的感性认识 创建一个包含简单内容的数

Android数据存储之SQLite 数据库学习

Android提供了五种存取数据的方式 (1)SharedPreference,存放较少的五种类型的数据,只能在同一个包内使用,生成XML的格式存放在设备中 (2) SQLite数据库,存放各种数据,是一个轻量级的嵌入式数据库 (3) File文件,通过读取写入方式生成文件存放数据 (4) ContentProvider,主要用于让其他应用程序使用保存的数据 (5)通过网络获取数据和写入数据到网络存储空间 SQLite 数据库介绍 SQLite 是一款轻量级的关系型数据库,它的运算速度非常快,占