Android中多表的SQLite數據庫(譯)

原文: Android SQLite Database with Multiple Tablesjava

  在上一篇教程Android SQLite Database Tutorial中,解釋瞭如何在你的Android應用中使用SQLite數據庫。但它只涵蓋了你的數據庫中只有一個表的情景。有不少人詢問當數據庫中有多個表時如何處理。android

  如下解釋了當有多個表存在時如何處理SQLite數據庫。sql

 

用例: Todo應用

  爲了便於理解,我在這一教程中用了一個真實的用例,一個TODO應用的數據庫方案。本文不會涵蓋如何設計應用的內容,但解釋了數據庫的設計,準備數據庫輔助類和模型。數據庫

 

數據庫設計

  我考慮了一個基本Todo應用,提供最小化的功能,像建立一個todo note賦予它一個tag(s)(類別)。所以咱們的數據庫只須要三個表。swift

  這三個表是:markdown

  todos - 存儲全部的todo notes數據庫設計

  tags - 存儲tags的列表ide

  todo_tags - 存儲賦給todo的tags函數

  下圖解釋了表的結構和表之間的關係:oop

 

開始一個新項目

  在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(); }
相關文章
相關標籤/搜索