美文网首页
任务5-1:运用SQLite数据库存储和访问数据

任务5-1:运用SQLite数据库存储和访问数据

作者: jingz课程 | 来源:发表于2018-03-29 11:24 被阅读0次

5.1 创建数据访问对象类

数据访问对象即Data Access Object(缩写为 DAO )。它向需要访问数据的模块提供接口调用,而隐藏数据库操作的具体细节。
虽然在UI代码中插入数据库操作代码并不会引起语法错误,但是从软件架构设计的角度来考虑,进行层次化的设计,更有利于使软件结构清晰,便于阅读、理解和维护。

步骤1:在我们应用程序的包下创建名为dao的子包:

步骤2:在dao包中创建名为NoteDAO数据访问对象类:

package com.jing.app.sn.dao;

public class NoteDAO {
    
}

步骤3:为NoteDAO类添加一个Context类型属性——后面的数据库操作需要这个对象:

public class NoteDAO {
    private Context context;

}

步骤4:将NoteDAO类改写成单例模式

按照之前学习过的单例模式实现方法,将NoteDAO类设置为单例:

public class NoteDAO {

    /**
     * 采用单例模式
     */
    private static NoteDAO sInstance;
    
    public static NoteDAO getInstance(Context context) {
        if (sInstance == null) {
            sInstance = new NoteDAO(context);
        }
        return sInstance;
    }

    private Context context;

    /**
     * 私有构造方法
     * @param context
     */
    private NoteDAO(Context context) {
        this.context = context;
    }
}

可以注意到,这次单例模式的实现中,稍有不同的是getInstance()方法多了一个Context类型的参数,这在后面的编码中要用到。

5.2 创建SQLiteOpenHelper子类

SQLiteOpenHelper类的基础上扩展(extends)我们自己的子类NoteDbHelper,通过它来创建、维护和获取我们的数据库对象。

从软件设计的角度考虑,我们没有必要在NoteDAO类之外的地方使用SQLiteOpenHelper对象。因此考虑将NoteDbHelper类定义为NoteDAO类的非公有静态内部类。

在NoteDAO类的内部创建静态(static)类NoteDbHelper并继承SQLiteOpenHelper类,然后添加必要构造方法并重写两个回调方法:

public class NoteDAO {
    ...
    static class NoteDbHelper extends SQLiteOpenHelper {

        public NoteDbHelper(Context context, String name, SQLiteDatabase.CursorFactory factory, int version) {
            super(context, name, factory, version);
        }

        @Override
        public void onCreate(SQLiteDatabase db) {

        }

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

        }
    }
}

对于NoteDbHelper类的构造方法,我们主要关注它的两个参数:

  • name: 数据库文件名。我们自定一个文件名提供给构造方法。
  • version: 数据库版本。如果在开发过程中要对数据库进行修改,如新建、删除数据表或修改数据表结构,则应提供大于当前版本的数值。

为NoteDAO类添加NoteDbHelper成员变量

NoteDAO类需要持有一个NoteDbHelper类对象,以便通过它来访问数据库。同时,要在NoteDAO类的构造方法中对其分配内存并设置参数。
找到NoteDAO类的构造方法,将其改写为如下形式:

    private NoteDAO(Context context) {
        this.context = context;
        dbHelper = new NoteDbHelper(context, "note.db", null, 1);
    }

当创建NoteDbHelper类对象时,构造方法被调用。此时:

  • 如果name参数指定的数据库文件不存在,就创建这个文件,并且调用onCreate()回调方法;
  • 如果version参数给出的版本号大于当前版本号,则调用onUpgrade()回调方法;

至于两个回调方法具体做什么,要由我们自己来定义。下面我们重点关注onCreate()回调方法。

5.3 创建note表

此时,在onCreate()中,我们只需要将note表创建起来。根据数据库设计,需要执行以下的SQL语句:

CREATE TABLE note (
id INTEGER PRIMARY KEY AUTOINCREMENT, 
title TEXT, 
content TEXT, 
createTime INTEGER
)

理论上,我们可以直接将这个SQL语句作为字符串参数,传递给SQLiteDatabase类的execSQL()方法来执行。但是,其中涉及到的表名("note")列名("id","title","content","createTime")除了用在这里,在之后的所有数据库访问操作中也仍然会经常使用。比较方便的做法是将它们定义为常量,这样便于引用。同样的道理,我们将数据库文件名称、版本号也定义为常量,以便统一管理维护。

创建常量文件

在包dao中创建名为Constants.java的源文件作为常量存放位置:

打开Constants.java,在其中定义各个常量:

public class Constants {
    // 数据库文件名
    public static final String DB_NAME = "note.db";

    // 数据库版本号
    public static final int VERSION = 1;

    // note表名字
    public static final String TABLE_NOTE = "note";

    // note表各列名字
    public static final String COL_ID = "_id";
    public static final String COL_TITLE = "title";
    public static final String COL_CONTENT = "content";
    public static final String COL_CREATE_TIME = "createTime";
}

于是,上面的建表SQL语句可以改写为:

"CREATE TABLE " + TABLE_NOTE + "(" +
    COL_ID + " INTEGER PRIMARY KEY AUTOINCREMENT, " +
    COL_TITLE + " TEXT, " +
    COL_CONTENT + " TEXT, " +
    COL_CREATE_TIME + " INTEGER)"

接下来,回到NoteDAO.java文件,在文件上部众多的"import ......"语句之后,添加如下语句以将这些常量导入(xxx.xxx.xx部分替换成你自己的应用程序包名):

import static xxx.xxx.xxx.dao.Constants.*;

这样就可以直接引用这些常量了。

用常量数据库名和版本号替换硬编码(hard code)

找到NoteDAO类的构造方法。在前面,我们已经在这里创建了NoteDbHelper类的实例:

    private NoteDAO(Context context) {
        this.context = context;
        dbHelper = new NoteDbHelper(context, "note.db", null, 1);
    }

用刚才定义的常量替换数据库文件版本两个参数,变成如下形式:

    private NoteDAO(Context context) {
        this.context = context;
        dbHelper = new NoteDbHelper(context, DB_NAME, null, VERSION);
    }

编写创建note表代码

回到NoteDbHelper类onCreate()方法,添加创建note表相关的代码:

db.execSQL("CREATE TABLE " + TABLE_NOTE + "(" +
            COL_ID + " INTEGER PRIMARY KEY AUTOINCREMENT, " +
            COL_TITLE + " TEXT, " +
            COL_CONTENT + " TEXT, " +
            COL_CREATE_TIME + " INTEGER)");

编写单元测试用例

由于我们目前还没有将数据库与应用程序主体部分对接,因此很难立即对刚才编写的数据库模块进行验证。可以运用Android的单元测试框架来解决这个问题。

首先我们为了测试方便,在NoteDAO类的构造函数下面增加如下的方法:

    NoteDbHelper getDbHelper() {
        return dbHelper;
    }

这个方法让同在dao包下的某个类可以获取到dbHelper对象。

接下来,找到名为androidTest的目录:

可以看到,androidTest下有一个和我们应用程序同名的包。在这个包下同样创建一个名为dao的子包,并在里面添加测试类NoteDAOTest

NoteDAOTest类编写测试代码如下:

@RunWith(AndroidJUnit4.class)
public class NoteDAOTest {
    @Test
    public void testCreateDatabase() throws Exception {
        Context context = InstrumentationRegistry.getTargetContext();
        NoteDAO dao = NoteDAO.getInstance(context);
        NoteDAO.NoteDbHelper dbHelper = dao.getDbHelper();

        // 取只读的数据库对象
        SQLiteDatabase db = dbHelper.getReadableDatabase();
        // 检查数据库对象是否获取成功
        assertNotNull(db);
        // 对note表进行一次查询
        Cursor cursor = db.query(Constants.TABLE_NOTE, null, null, null, null, null, null);
        // 检查查询操作是否成功
        assertNotNull(cursor);
    }
}

然后右键单击NoteDAOTest类,在菜单中选择“Run 'NoteDAOTest'”并执行。如果测试通过,在Android Studio窗口下方将显示如下的信息:

整个单元测试执行流程如下:

相关文章

网友评论

      本文标题:任务5-1:运用SQLite数据库存储和访问数据

      本文链接:https://www.haomeiwen.com/subject/wrrpcftx.html