Android中使用android.database.sqlite.SQLiteDatabase來表示一個數據庫對象,它提供了兩種模式來幫助開發者進行增刪改查等基本數據庫操做。java
//利用sql查詢數據 Cursor data = db.rawQuery("select id,name from table"); //利用sql插入數據 db.execSql("insert into contacts (id,name) values (2,'cpacm')");
//結構化的方式查詢數據 Cursor data = db.query("contacts",new String[]{"id","name"},null,null,null,null,null); //結構化方式插入數據 ContentValue values = new ContentValues(); values.put("id",2); values.put("name","cpacm"); db.insert("table",null,values);
/** * 參數說明 * table:數據表名,columns:須要顯示的列名,若是爲null則至關與* * selection:至關於sql語句的where條件;selectionArgs數組放的是where條件要替換的?號 * groupBy:SQL語句的Group, orderBy: 排序,默認asc **/ public Cursor query (String table, String[] columns, String selection, String[] selectionArgs, String groupBy, String having, String orderBy){
}
好比說我要查詢的SQL語句爲
android
SELECT CustomerName, SUM(OrderPrice) FROM Orders WHERE Country=? GROUP BY CustomerName HAVING SUM(OrderPrice)>500 ORDER BY CustomerName
那麼我寫的代碼以下sql
//數據表名 String table = "Orders" ; //要顯示的列名 String[] columns = new String[] { "CustomerName" , "SUM(OrderPrice)" }; //選擇條件 String selection = "Country=?" ; //裏面的變量對應條件中的問號,多個的時候請一一入座。 String[] selectionArgs = new String[]{ "China" }; //分組名 String groupBy = "CustomerName" ; //分組的條件 String having = "SUM(OrderPrice)>500" ; //按字段排序 String orderBy = "CustomerName" ; Cursor c = db.query(table, columns, selection, selectionArgs, groupBy, having, orderBy);
這樣就能實現數據庫的查詢了。其它的語句參數都是差很少的,這裏就不一一介紹了。
shell
public long insert (String table, String nullColumnHack, ContentValues values)
public int delete(String table, String whereClause, String[] whereArgs)
public int update(String table, ContentValues values, String whereClause, String[] whereArgs)
課外小知識:關於GroupBy和Having的使用
group by 顧名思義就是按照xxx進行分組,它必須有「聚合函數」來配合才能使用,使用時至少須要一個分組標識字段。聚合函數有:sum()、count()、avg()等,使用group by目的就是要將數據分組進行彙總操做。好比上面sql語句的CustomerName,若是它有四個行{「張三」,「李四」,「張三」,「李四」},那麼此時就會分紅兩組,分別爲張三組和李四組,而後統計出他們使用的orderprice總和。
HAVING做用就是爲每個組指定條件,像where指定條件同樣,也就是說,能夠根據你指定的條件來選擇行。若是你要使用HAVING子句的話,它必須處在GROUP BY子句以後。仍是上面的SQL語句,若是張三的SUM(OrderPrice)沒有超過500,那麼張三組就不會顯示。數據庫
//編譯複雜的SQL語句 SQLiteStatement compiledSql = db.compileStatement(aSQL); //執行SQL compiledSql.execute();
除此之外,Android還提供了豐富的高級數據庫功能,好比支持觸發器、支持複合索引以及支持對數據庫事務的處理。
數組
try{ db.beginTransaction(); //執行相關的數據庫操做,若有異常,直接進入finally部分。 }finally{ //不論成功都要調用endTransaction來結束事務 db.endTransaction(); }
課外小知識:所謂事務是用戶定義的一個數據庫操做序列,這些操做要麼全作要麼全不作,是一個不可分割的工做單位。例如,在關係數據庫中,一個事務能夠是一條SQL語句、一組SQL語句或整個程序。 簡單舉個例子就是你要同時修改數據庫中兩個不一樣表的時候,若是它們不是一個事務的話,當第一個表修改完,但是第二表改修出現了異常而沒能修改的狀況下,就只有第二個表回到未修改以前的狀態,而第一個表已經被修改完畢。 而當你把它們設定爲一個事務的時候,當第一個表修改完,但是第二表改修出現了異常而沒能修改的狀況下,第一個表和第二個表都要回到未修改的狀態!這就是所謂的事務回滾。服務器
package com.example.notebook; import android.content.Context; import android.database.sqlite.SQLiteDatabase; import android.database.sqlite.SQLiteOpenHelper; import android.database.sqlite.SQLiteDatabase.CursorFactory; public class DBHelper extends SQLiteOpenHelper{ private static final int VERSION=1; /** * 在SQLiteOpenHelper的子類當中,必須有該構造函數 * @param context 上下文對象 * @param name 數據庫名稱 * @param factory * @param version 當前數據庫的版本,值必須是整數而且是遞增的狀態 */ public DBHelper(Context context,String name,CursorFactory factory,int version){ super(context,name,factory,version); } public DBHelper(Context context, String name, int version){ this(context,name,null,version); } public DBHelper(Context context, String name){ this(context,name,VERSION); } @Override public void onCreate(SQLiteDatabase db) { // 數據庫首次構造時,會調用該函數,能夠在這裏構造表、索引,等等 System.out.println("create a database"); //execSQL用於執行SQL語句 db.execSQL("create table notebook(_id integer primary key autoincrement,pic varchar(50),title varchar(20),content text,time varchar)"); } @Override public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) { // 若是給定的當前數據庫版本高於已有數據庫版本,調用該函數 System.out.println("upgrade a database"); } }
package com.example.notebook; import android.content.ContentValues; import android.content.Context; import android.database.Cursor; import android.database.sqlite.SQLiteDatabase; import android.database.sqlite.SQLiteException; import android.util.Log; public class DBManager { private Context mContext = null; private SQLiteDatabase mSQLiteDatabase = null;//用於操做數據庫的對象 private DBHelper dh = null;//用於建立數據庫的對象 private String dbName = "note.db";//數據庫的名稱 private int dbVersion = 1;//數據庫的版本 public DBManager(Context context){ mContext = context; } public void open(){ try{ dh = new DBHelper(mContext, dbName, null, dbVersion);//創建數據庫 if(dh == null){ Log.v("msg", "is null"); return ; } mSQLiteDatabase = dh.getWritableDatabase();//以可寫方式打開數據庫 //dh.onOpen(mSQLiteDatabase); }catch(SQLiteException se){ se.printStackTrace(); } } public void close(){ mSQLiteDatabase.close();//關閉數據庫 dh.close(); } public Cursor selectAll(){ Cursor cursor = null; try{ //sql語句操做 String sql = "select * from notebook"; cursor = mSQLiteDatabase.rawQuery(sql, null); }catch(Exception ex){ ex.printStackTrace(); cursor = null; } return cursor; } public Cursor selectById(int id){ //String result[] = {}; Cursor cursor = null; try{ //sql語句操做 String sql = "select * from notebook where _id='" + id +"'"; cursor = mSQLiteDatabase.rawQuery(sql, null); }catch(Exception ex){ ex.printStackTrace(); cursor = null; } return cursor; } public long insert(String title, String content,String pic){ long datetime = System.currentTimeMillis(); long l = -1; try{ //結構化方式操做 ContentValues cv = new ContentValues(); cv.put("title", title); cv.put("content", content); cv.put("time", datetime); cv.put("pic", pic); l = mSQLiteDatabase.insert("notebook", null, cv); // Log.v("datetime", datetime+""+l); }catch(Exception ex){ ex.printStackTrace(); l = -1; } return l; } public int delete(int id){ int affect = 0; try{ //結構化方式操做 affect = mSQLiteDatabase.delete("notebook", "_id=?", new String[]{String.valueOf(id)}); }catch(Exception ex){ ex.printStackTrace(); affect = -1; } return affect; } public int update(int id, String title, String content,String pic){ int affect = 0; try{ //結構化方式操做 ContentValues cv = new ContentValues(); cv.put("title", title); cv.put("content", content); cv.put("pic", pic); String w[] = {String.valueOf(id)}; affect = mSQLiteDatabase.update("notebook", cv, "_id=?", w); }catch(Exception ex){ ex.printStackTrace(); affect = -1; } return affect; } }
獲取數據示例
網絡
private DBManager dm = null;// 數據庫管理對象
private Cursor cursor = null;
dm = new DBManager(this);//數據庫操做對象 dm.open();//打開數據庫操做對象 cursor = dm.selectAll();//獲取全部數據 cursor.moveToFirst();//將遊標移動到第一條數據,使用前必須調用 int count = cursor.getCount();//個數 ArrayList<String> contents = new ArrayList<String>();//圖片的全部集合 ArrayList<String> imgs = new ArrayList<String>();//圖片的全部集合 ArrayList<String> items = new ArrayList<String>();//標題的全部集合 ArrayList<String> times = new ArrayList<String>();//時間的全部集合 for(int i= 0; i < count; i++){ contents.add(cursor.getString(cursor.getColumnIndex("content"))); imgs.add(cursor.getString(cursor.getColumnIndex("pic"))); items.add(cursor.getString(cursor.getColumnIndex("title"))); times.add(cursor.getString(cursor.getColumnIndex("time")));
//cursor.getInt(cursor.getColumnIndex("_id")) cursor.moveToNext();//將遊標指向下一個 } dm.close();//關閉數據操做對象
本質上而言,雲端存儲就是經過網絡將移動設備上的數據存儲到遠端服務器上。在Android中,增長了一些輔助功能,使得整個流程的實現變得更爲簡單。首先是經過Google帳號來標識用戶身份。在android中,默認支持使用Google帳號做爲用戶身份的標識,系統上各個應用均可以經過帳號系統得到用戶的登陸信息。其次,有了Google帳號,使得開發者不須要自行構建後臺服務系統。
架構
Android的雲端數據存取由系統服務BackupManagerService來統一管理。當應用提交備份數據請求時,BackupManagerService會將該請求放入備份隊列中,該隊列會按照必定的控制邏輯定時提交到雲端。當有新應用安裝到系統時,會觸發數據恢復事件,BackupManagerService會憑藉應用包名和用戶帳號從雲端取出相應的備份數據,嘗試恢復。併發
在實踐中,Android會構造一個派生自BackupAgent類的子類android.app.backup.BackupAgentHelper的對象,來更方便地構建雲端存儲組件。
import java.io.File; import java.io.IOException; import android.app.backup.BackupAgentHelper; import android.app.backup.BackupDataInput; import android.app.backup.BackupDataOutput; import android.app.backup.FileBackupHelper; import android.os.ParcelFileDescriptor; public class MyBackupAgent extends BackupAgentHelper { private static final String KEY = "my_backup"; @Override public void onCreate() { //構造文件讀寫對象,聲明須要備份的文件 FileBackupHelper helper = new FileBackupHelper(this,"backup_file"); addHelper(KEY,helper); super.onCreate(); } @Override public void onBackup(ParcelFileDescriptor oldState, BackupDataOutput data, ParcelFileDescriptor newState) throws IOException { //調用父類方法,提交整個文件到雲端 super.onBackup(oldState, data, newState); } @Override public void onRestore(BackupDataInput data, int appVersionCode, ParcelFileDescriptor newState) throws IOException { // 調用父類方法,將從雲端獲取的文件覆蓋本地文件 super.onRestore(data, appVersionCode, newState); } @Override public void onRestoreFile(ParcelFileDescriptor data, long size, File destination, int type, long mode, long mtime) throws IOException { // TODO Auto-generated method stub super.onRestoreFile(data, size, destination, type, mode, mtime); }
Android不會自行將數據提交到雲端,開發者須要顯性調用android.app.backup.BackupManager的dataChanged函數來觸發。
和全部組件同樣,雲端存儲組件是由系統進行託管的。這就須要把組件的相關信息放入配置文件中。
<application android:backupAgent = "MyBackupAgent" ...>
到這裏,數據的部分就講解的差很少了,剩下的就要回到咱們的數據源組件ContentProvider了。 數據這一塊對於開發者來講相當重要,怎樣使用,如何作最有效率,這些問題也是咱們技術員要一直研究的重點。 參考文章:Android 的Backup服務管理機制與架構分析 http://blog.csdn.net/goohong/article/details/8026045