Android中多表的SQLite数据库(译)

原文: Android SQLite Database with Multiple Tables

  在上一篇教程Android SQLite Database Tutorial中,解释了如何在你的Android应用中使用SQLite数据库。但它只涵盖了你的数据库中只有一个表的情景。有很多人询问当数据库中有多个表时如何处理。

  以下解释了当有多个表存在时如何处理SQLite数据库。

用例: Todo应用

  为了便于理解,我在这一教程中用了一个真实的用例,一个TODO应用的数据库方案。本文不会涵盖如何设计应用的内容,但解释了数据库的设计,准备数据库辅助类和模型。

数据库设计

  我考虑了一个基本Todo应用,提供最小化的功能,像创建一个todo note赋予它一个tag(s)(类别)。因此我们的数据库只需要三个表。

  这三个表是:

  todos - 存储所有的todo notes

  tags - 存储tags的列表

  todo_tags - 存储赋给todo的tags

  下图解释了表的结构和表之间的关系:

开始一个新项目

  在Eclipse中创建一个新项目:

  1. 在Eclipse中通过File ⇒ New ⇒ Android ⇒ Application Project创建一个新项目。我将包命名为info.androidhive.sqlite并将主活动命名为MainActivity.java

  2. 我们需要额外两个包存放辅助类和模型类。右键src ⇒ New ⇒ Package并将它命名为info.androidhive.sqlite.helperinfo.androidhive.sqlite.model

为表创建模型类

  下一步是为我们的数据库表创建模型类,将每一单行作为一个对象即可。我们只需要todostags两个模型。对于todo_tags我们不需要一个模型类。

  3. 在info.androidhive.sqlite.helper中创建一个新的类,代码如下。这是todos表的模型类。

Todo.java

package info.androidhive.sqlite.model;

public class Todo {

    int id;
    String note;
    int status;
    String created_at;

    // constructors
    public Todo() {
    }

    public Todo(String note, int status) {
        this.note = note;
        this.status = status;
    }

    public Todo(int id, String note, int status) {
        this.id = id;
        this.note = note;
        this.status = status;
    }

    // setters
    public void setId(int id) {
        this.id = id;
    }

    public void setNote(String note) {
        this.note = note;
    }

    public void setStatus(int status) {
        this.status = status;
    }

    public void setCreatedAt(String created_at){
        this.created_at = created_at;
    }

    // getters
    public long getId() {
        return this.id;
    }

    public String getNote() {
        return this.note;
    }

    public int getStatus() {
        return this.status;
    }
}

  4. 在同一个包中为tags表创建另一个模型类,命名为Tags.java。

Tag.java

package info.androidhive.sqlite.model;

public class Tag {

    int id;
    String tag_name;

    // constructors
    public Tag() {

    }

    public Tag(String tag_name) {
        this.tag_name = tag_name;
    }

    public Tag(int id, String tag_name) {
        this.id = id;
        this.tag_name = tag_name;
    }

    // setter
    public void setId(int id) {
        this.id = id;
    }

    public void setTagName(String tag_name) {
        this.tag_name = tag_name;
    }

    // getter
    public int getId() {
        return this.id;
    }

    public String getTagName() {
        return this.tag_name;
    }
}

数据库辅助类

  数据库辅助类包含所有执行数据库操作的方法,例如打开连接,关闭连接,插入,更新,读取,删除等等。因为这个类是个辅助类,将它放在helper包下。

  5. 在info.androidhive.sqlite.helper创建另一个类,命名为DatabaseHelper.java,继承自SQLiteOpenHelper

public class DatabaseHelper extends SQLiteOpenHelper {

  6. 添加所需的变量,例如数据库名称,数据库版本号,列名称。我还在onCreate()方法中执行了建表语句。在DatabaseHelper.java中写如下代码:

DatabaseHelper.java

public class DatabaseHelper extends SQLiteOpenHelper {

    // Logcat tag
    private static final String LOG = "DatabaseHelper";

    // Database Version
    private static final int DATABASE_VERSION = 1;

    // Database Name
    private static final String DATABASE_NAME = "contactsManager";

    // Table Names
    private static final String TABLE_TODO = "todos";
    private static final String TABLE_TAG = "tags";
    private static final String TABLE_TODO_TAG = "todo_tags";

    // Common column names
    private static final String KEY_ID = "id";
    private static final String KEY_CREATED_AT = "created_at";

    // NOTES Table - column nmaes
    private static final String KEY_TODO = "todo";
    private static final String KEY_STATUS = "status";

    // TAGS Table - column names
    private static final String KEY_TAG_NAME = "tag_name";

    // NOTE_TAGS Table - column names
    private static final String KEY_TODO_ID = "todo_id";
    private static final String KEY_TAG_ID = "tag_id";

    // Table Create Statements
    // Todo table create statement
    private static final String CREATE_TABLE_TODO = "CREATE TABLE "
            + TABLE_TODO + "(" + KEY_ID + " INTEGER PRIMARY KEY," + KEY_TODO
            + " TEXT," + KEY_STATUS + " INTEGER," + KEY_CREATED_AT
            + " DATETIME" + ")";

    // Tag table create statement
    private static final String CREATE_TABLE_TAG = "CREATE TABLE " + TABLE_TAG
            + "(" + KEY_ID + " INTEGER PRIMARY KEY," + KEY_TAG_NAME + " TEXT,"
            + KEY_CREATED_AT + " DATETIME" + ")";

    // todo_tag table create statement
    private static final String CREATE_TABLE_TODO_TAG = "CREATE TABLE "
            + TABLE_TODO_TAG + "(" + KEY_ID + " INTEGER PRIMARY KEY,"
            + KEY_TODO_ID + " INTEGER," + KEY_TAG_ID + " INTEGER,"
            + KEY_CREATED_AT + " DATETIME" + ")";

    public DatabaseHelper(Context context) {
        super(context, DATABASE_NAME, null, DATABASE_VERSION);
    }

    @Override
    public void onCreate(SQLiteDatabase db) {

        // creating required tables
        db.execSQL(CREATE_TABLE_TODO);
        db.execSQL(CREATE_TABLE_TAG);
        db.execSQL(CREATE_TABLE_TODO_TAG);
    }

    @Override
    public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
        // on upgrade drop older tables
        db.execSQL("DROP TABLE IF EXISTS " + TABLE_TODO);
        db.execSQL("DROP TABLE IF EXISTS " + TABLE_TAG);
        db.execSQL("DROP TABLE IF EXISTS " + TABLE_TODO_TAG);

        // create new tables
        onCreate(db);
    }

CRUD (Create, Read, Update and Delete) 操作

  现在起我们将一个方法一个方法地完善DatabaseHelper.class

1. 创建一个Todo

  这个方法将会在todos表中创建一个todo条目。在同一个方法中,我们还会赋予todo一个tag名称,这会在todo_tags表中插入一行。

/*
 * Creating a todo
 */
public long createToDo(Todo todo, long[] tag_ids) {
    SQLiteDatabase db = this.getWritableDatabase();

    ContentValues values = new ContentValues();
    values.put(KEY_TODO, todo.getNote());
    values.put(KEY_STATUS, todo.getStatus());
    values.put(KEY_CREATED_AT, getDateTime());

    // insert row
    long todo_id = db.insert(TABLE_TODO, null, values);

    // assigning tags to todo
    for (long tag_id : tag_ids) {
        createTodoTag(todo_id, tag_id);
    }

    return todo_id;
}

2. 获取一个Todo

  以下将会从todos表中获取一个todo对象。

SELECT * FROM todos WHERE id = 1;

/*
 * get single todo
 */
public Todo getTodo(long todo_id) {
    SQLiteDatabase db = this.getReadableDatabase();

    String selectQuery = "SELECT  * FROM " + TABLE_TODO + " WHERE "
            + KEY_ID + " = " + todo_id;

    Log.e(LOG, selectQuery);

    Cursor c = db.rawQuery(selectQuery, null);

    if (c != null)
        c.moveToFirst();

    Todo td = new Todo();
    td.setId(c.getInt(c.getColumnIndex(KEY_ID)));
    td.setNote((c.getString(c.getColumnIndex(KEY_TODO))));
    td.setCreatedAt(c.getString(c.getColumnIndex(KEY_CREATED_AT)));

    return td;
}

3. 获取所有Todo对象

  获取所有的todo对象包含读取所有的todo行,并添加到一个列表中。

SELECT * FROM todos;

/*
 * getting all todos
 * */
public List<Todo> getAllToDos() {
    List<Todo> todos = new ArrayList<Todo>();
    String selectQuery = "SELECT  * FROM " + TABLE_TODO;

    Log.e(LOG, selectQuery);

    SQLiteDatabase db = this.getReadableDatabase();
    Cursor c = db.rawQuery(selectQuery, null);

    // looping through all rows and adding to list
    if (c.moveToFirst()) {
        do {
            Todo td = new Todo();
            td.setId(c.getInt((c.getColumnIndex(KEY_ID))));
            td.setNote((c.getString(c.getColumnIndex(KEY_TODO))));
            td.setCreatedAt(c.getString(c.getColumnIndex(KEY_CREATED_AT)));

            // adding to todo list
            todos.add(td);
        } while (c.moveToNext());
    }

    return todos;
}

4. 获取一个Tag标签下的所有Todo对象

  这和读取所有行相同,但要按照Tag标签过滤todo对象。查看下面的查询语句,它按照tag标签的监视列表来获取todo对象。

SELECT * FROM todos td, tags tg, todo_tags tt WHERE tg.tag_name = ‘Watchlist’ AND tg.id = tt.tag_id AND td.id = tt.todo_id;

/*
 * getting all todos under single tag
 * */
public List<Todo> getAllToDosByTag(String tag_name) {
    List<Todo> todos = new ArrayList<Todo>();

    String selectQuery = "SELECT  * FROM " + TABLE_TODO + " td, "
            + TABLE_TAG + " tg, " + TABLE_TODO_TAG + " tt WHERE tg."
            + KEY_TAG_NAME + " = ‘" + tag_name + "‘" + " AND tg." + KEY_ID
            + " = " + "tt." + KEY_TAG_ID + " AND td." + KEY_ID + " = "
            + "tt." + KEY_TODO_ID;

    Log.e(LOG, selectQuery);

    SQLiteDatabase db = this.getReadableDatabase();
    Cursor c = db.rawQuery(selectQuery, null);

    // looping through all rows and adding to list
    if (c.moveToFirst()) {
        do {
            Todo td = new Todo();
            td.setId(c.getInt((c.getColumnIndex(KEY_ID))));
            td.setNote((c.getString(c.getColumnIndex(KEY_TODO))));
            td.setCreatedAt(c.getString(c.getColumnIndex(KEY_CREATED_AT)));

            // adding to todo list
            todos.add(td);
        } while (c.moveToNext());
    }

    return todos;
}

5. 更新一个Todo

  下面的方法将会更新一个todo。它只会更新todo的值,不包括tag标签。

/*
 * Updating a todo
 */
public int updateToDo(Todo todo) {
    SQLiteDatabase db = this.getWritableDatabase();

    ContentValues values = new ContentValues();
    values.put(KEY_TODO, todo.getNote());
    values.put(KEY_STATUS, todo.getStatus());

    // updating row
    return db.update(TABLE_TODO, values, KEY_ID + " = ?",
            new String[] { String.valueOf(todo.getId()) });
}

6. 删除一个Todo

  将todo的id传给下面的方法,从数据库中删除一项todo。

/*
 * Deleting a todo
 */
public void deleteToDo(long tado_id) {
    SQLiteDatabase db = this.getWritableDatabase();
    db.delete(TABLE_TODO, KEY_ID + " = ?",
            new String[] { String.valueOf(tado_id) });
}

  到目前为止我们已经给todos表创建了CRUD方法。现在我们开始给tags表创建所需的方法。

7. 创建一个Tag

  下面的方法将会给tags表插入一行。

/*
 * Creating tag
 */
public long createTag(Tag tag) {
    SQLiteDatabase db = this.getWritableDatabase();

    ContentValues values = new ContentValues();
    values.put(KEY_TAG_NAME, tag.getTagName());
    values.put(KEY_CREATED_AT, getDateTime());

    // insert row
    long tag_id = db.insert(TABLE_TAG, null, values);

    return tag_id;
}

8. 获取所有的Tag标签

  在tags表中执行查询所有的语句将会给你一个tag标签的列表。

SELECT * FROM tags;

/**
 * getting all tags
 * */
public List<Tag> getAllTags() {
    List<Tag> tags = new ArrayList<Tag>();
    String selectQuery = "SELECT  * FROM " + TABLE_TAG;

    Log.e(LOG, selectQuery);

    SQLiteDatabase db = this.getReadableDatabase();
    Cursor c = db.rawQuery(selectQuery, null);

    // looping through all rows and adding to list
    if (c.moveToFirst()) {
        do {
            Tag t = new Tag();
            t.setId(c.getInt((c.getColumnIndex(KEY_ID))));
            t.setTagName(c.getString(c.getColumnIndex(KEY_TAG_NAME)));

            // adding to tags list
            tags.add(t);
        } while (c.moveToNext());
    }
    return tags;
}

9. 更新Tags

  下面的方法将会更新tag。

/*
 * Updating a tag
 */
public int updateTag(Tag tag) {
    SQLiteDatabase db = this.getWritableDatabase();

    ContentValues values = new ContentValues();
    values.put(KEY_TAG_NAME, tag.getTagName());

    // updating row
    return db.update(TABLE_TAG, values, KEY_ID + " = ?",
            new String[] { String.valueOf(tag.getId()) });
}

10. 删除一个Tag标签下的所有Tag和Todo对象。

  下面的方法将会从数据库中删除一个tag。它也会删除该tag标签下的所有todo对象,但这一行为是可选的。

should_delete_all_tag_todos = 传递true代表将会删除tag标签下的所有todo对象。

/*
 * Deleting a tag
 */
public void deleteTag(Tag tag, boolean should_delete_all_tag_todos) {
    SQLiteDatabase db = this.getWritableDatabase();

    // before deleting tag
    // check if todos under this tag should also be deleted
    if (should_delete_all_tag_todos) {
        // get all todos under this tag
        List<Todo> allTagToDos = getAllToDosByTag(tag.getTagName());

        // delete all todos
        for (Todo todo : allTagToDos) {
            // delete todo
            deleteToDo(todo.getId());
        }
    }

    // now delete the tag
    db.delete(TABLE_TAG, KEY_ID + " = ?",
            new String[] { String.valueOf(tag.getId()) });
}

  下面是访问todo_tags表中数据的方法。

11. 给Todo对象分配一个Tag

  下面的方法将会给一个todo对象赋予一个tag标签。你也可以通过调用这个函数多次将多个tag赋予同一个todo对象。

/*
 * Creating todo_tag
 */
public long createTodoTag(long todo_id, long tag_id) {
    SQLiteDatabase db = this.getWritableDatabase();

    ContentValues values = new ContentValues();
    values.put(KEY_TODO_ID, todo_id);
    values.put(KEY_TAG_ID, tag_id);
    values.put(KEY_CREATED_AT, getDateTime());

    long id = db.insert(TABLE_TODO_TAG, null, values);

    return id;
}

12. 移除Todo的Tag

  下面的方法将会移除赋予给一个todo的tag。

/**
 * Deleting a todo tag
 */
public void deleteToDoTag(long id) {
    SQLiteDatabase db = this.getWritableDatabase();
    db.delete(TABLE_TODO, KEY_ID + " = ?",
            new String[] { String.valueOf(id) });
}

13. 改变todo的tag

  下面的方法简单地替换了一个todo的tag标签。

/*
 * Updating a todo tag
 */
public int updateNoteTag(long id, long tag_id) {
    SQLiteDatabase db = this.getWritableDatabase();

    ContentValues values = new ContentValues();
    values.put(KEY_TAG_ID, tag_id);

    // updating row
    return db.update(TABLE_TODO, values, KEY_ID + " = ?",
            new String[] { String.valueOf(id) });
}

14. 关闭数据库连接

  重要的一点一旦你使用完了数据库,不要忘了关闭数据库连接。当你无需再访问数据库时,调用下面的方法。

//closing database
public void closeDB() {
    SQLiteDatabase db = this.getReadableDatabase();
    if (db != null && db.isOpen())
        db.close();
}

原文地址:https://www.cnblogs.com/dogdogwang/p/10988888.html

时间: 2024-11-10 16:14:40

Android中多表的SQLite数据库(译)的相关文章

在Android中查看和管理sqlite数据库

http://www.cnblogs.com/walkingp/archive/2011/03/28/1997437.html 在Android中查看和管理sqlite数据库 在Android中可以使用Eclipse插件DDMS来查看,也可以使用Android工具包中的adb工具来查看.android项目中的sqlite数据库位于/data/data/项目包/databases中. 使用DDMS导出sqlite数据库. 1.首先打开android项目的调试模式,然后找到显示DDMS: 选择DDM

Adobe AIR中使用Flex连接Sqlite数据库(1)(创建数据库和表,以及同步和异步执行模式)

系列文章导航 Adobe AIR中使用Flex连接Sqlite数据库(1)(创建数据库和表) Adobe AIR中使用Flex连接Sqlite数据库(2)(添加,删除,修改以及语句参数) Adobe AIR中使用Flex连接Sqlite数据库(3)(查询) Adobe AIR中使用Flex连接Sqlite数据库(4)(事务) Flex,Fms3相关文章索引 Fms3和Flex打造在线多人视频会议和视频聊天(附原代码) 免费美女视频聊天,多人视频会议功能加强版本(Fms3和Flex开发(附源码))

Android中内容提供者ContentProvider实现数据库增删改查

1.我们首先new一个我们自己的类集成ContentProvider,并实现方法如下 package com.wzw.sqllitedemo.providers; import com.wzw.sqllitedemo.db.PersonSQLiteOpenHelper; import android.content.ContentProvider; import android.content.ContentUris; import android.content.ContentValues;

【最后的冲刺】android中excel表的导入和数据处理

[最后的冲刺]android中excel表的导入和数据处理 --学校课程的查询和修改 1.编写 The Class类把课程表courses.db当做一个实体类,hashcode和equals这两个类是为了判断输入的查询内容和Excel表中的内容是否一致. 并在java里面区别两个对象是否一致 1 public class TheClass { 2 private String classname; 3 private String type; 4 private String teacher;

在Android程序中使用已有的SQLite数据库

已经将这篇文章迁移至 Code问答,你也能够到这里查看这篇文章,请多多关注我的新技术博客CodeWenDa.com 在中文搜索中,没有找到一篇比較好的关于怎样在Android应用中使用自己事先创建好的数据库的文章,于是在谷歌上找到这篇英文文章,依照它的步骤,測试成功.决定把这篇文章大致的翻译一下,想看原文的能够点击这里:http://www.reigndesign.com/blog/using-your-own-sqlite-database-in-android-applications/ .

Android笔记(三十九) Android中的数据存储——SQLite(一)

SQLite是内置于Android的一款轻量级关系型数据库,她运算速度快,占用资源少,通常只需要几百K的内存就足够了,因而特别适合在移动设备上使用. SQLite不仅支持标准的SQL语法,还遵循数据库的ACID事务,所以如果有其他数据库基础,会上手很快.与其他数据库不同的是,SQLite不用设置用户名和密码就可以使用. 和其他数据库不同的是,SQLite没有其他数据库那么多繁杂的数据类型,它的数据类型很简单:integer表示整型,real表示浮点型,text表示文本类型,blob表示二进制类型

Android内部自带的SQLite数据库操作dos命令

1:什么叫做SQLite数据库 Android系统内核是Linux系统,Android系统很特殊,他自带了一个SQLite数据库,轻量型的一款嵌入式的数据库 它占用资源非常的低,在嵌入式设备中,可能只需要几百K的内存就够了.操作简单,你如果是之前学过其他的数据库的基础的话, 操作起来可以说是举手之劳. 2:这个SQLite数据库的数据类型有哪些. Integer  整型  有符号整数 -1,0,1,2,3- Real 浮点型以 8字节 IEEE 浮点数存储. Text. 值是文本字符串,使用数据

Android菜鸟成长记11 -- sqlite数据库的设计和升降级

Google为Andriod的较大的数据处理提供了SQLite,他在数据存储.管理.维护等各方面都相当出色,功能也非常的强大.SQLite具备下列特点: 1.轻量级 使用 SQLite 只需要带一个动态库,就可以享受它的全部功能,而且那个动态库的尺寸想当小. 2.独立性 SQLite 数据库的核心引擎不需要依赖第三方软件,也不需要所谓的"安装". 3.隔离性 SQLite 数据库中所有的信息(比如表.视图.触发器等)都包含在一个文件夹内,方便管理和维护. 4.跨平台 SQLite 目前

Android批量插入数据到SQLite数据库

Android中在sqlite插入数据的时候默认一条语句就是一个事务,因此如果存在上万条数据插入的话,那就需要执行上万次插入操作,操作速度可想而知.因此在Android中插入数据时,使用批量插入的方式可以大大提高插入速度. 有时需要把一些数据内置到应用中,常用的有以下2种方式:其一直接拷贝制作好的SQLite数据库文件,其二是使用系统提供的数据库,然后把数据批量插入.我更倾向于使用第二种方式:使用系统创建的数据库,然后批量插入数据.批量插入数据也有很多方法,那么那种方法更快呢,下面通过一个dem