溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊(cè)×
其他方式登錄
點(diǎn)擊 登錄注冊(cè) 即表示同意《億速云用戶服務(wù)條款》

Android的數(shù)據(jù)庫(kù)怎么使用

發(fā)布時(shí)間:2022-01-12 20:08:05 來(lái)源:億速云 閱讀:331 作者:iii 欄目:移動(dòng)開(kāi)發(fā)

今天小編給大家分享一下Android的數(shù)據(jù)庫(kù)怎么使用的相關(guān)知識(shí)點(diǎn),內(nèi)容詳細(xì),邏輯清晰,相信大部分人都還太了解這方面的知識(shí),所以分享這篇文章給大家參考一下,希望大家閱讀完這篇文章后有所收獲,下面我們一起來(lái)了解一下吧。

一、Android數(shù)據(jù)庫(kù)使用

Android中使用android.database.sqlite.SQLiteDatabase來(lái)表示一個(gè)數(shù)據(jù)庫(kù)對(duì)象,它提供了兩種模式來(lái)幫助開(kāi)發(fā)者進(jìn)行增刪改查等基本數(shù)據(jù)庫(kù)操作。

利用SQL語(yǔ)句描述操作
利用SQL語(yǔ)句調(diào)用SQLiteDatabase.execSql或SQLiteDatabase.rawQuery來(lái)執(zhí)行操作。

//利用sql查詢數(shù)據(jù) Cursor data = db.rawQuery("select id,name from table");  //利用sql插入數(shù)據(jù) db.execSql("insert into contacts (id,name) values (2,'cpacm')");

稍微學(xué)過(guò)sql語(yǔ)句的人應(yīng)該都看的懂上面的代碼(其實(shí)看語(yǔ)句的意思也能知道個(gè)大概~)
在 這里我來(lái)解釋一下Cursor(游標(biāo))的作用吧,游標(biāo)不能顧名思義(up主當(dāng)時(shí)學(xué)習(xí)數(shù)據(jù)庫(kù)時(shí)一度將游標(biāo)當(dāng)做與C語(yǔ)言里面的指針變量一樣,雖然有點(diǎn)對(duì),但意 思還是理解錯(cuò)了),Cursor它是系統(tǒng)為用戶開(kāi)設(shè)的一個(gè)數(shù)據(jù)緩沖區(qū),是的,它是一塊數(shù)據(jù)區(qū)域,存放SQL語(yǔ)句的執(zhí)行結(jié)果。但是它也提供了能從包括多條數(shù) 據(jù)記錄的結(jié)果集中每次提取一條記錄的機(jī)制,這一點(diǎn)也跟指針很像。游標(biāo)總是與一條SQL選擇語(yǔ)句相關(guān)聯(lián)因?yàn)橛螛?biāo)由結(jié)果集(可以是零條、一條或由相關(guān)的選擇語(yǔ) 句檢索出的多條記錄)和結(jié)果集中指向特定記錄的游標(biāo)位置組成。當(dāng)決定對(duì)結(jié)果集進(jìn)行處理  時(shí),必須聲明一個(gè)指向該結(jié)果集的游標(biāo)。用C語(yǔ)言作比較的話,如果寫過(guò)對(duì)文件進(jìn)行處理的程序,那么游標(biāo)就像您打開(kāi)文件所得到的文件句柄一樣,只要文件打開(kāi)成 功,該文件句柄就可代表該文件??傊涀。螛?biāo)是一塊有著特有記號(hào)的一塊數(shù)據(jù)區(qū)域,能夠讓用戶逐條從中讀取出數(shù)據(jù)。
結(jié)構(gòu)化的方式描述數(shù)據(jù)庫(kù)的操作
這樣即使我們不熟悉SQL語(yǔ)句,也能使用最熟悉的面向?qū)ο蟮姆绞竭M(jìn)行數(shù)據(jù)庫(kù)操作。

  1. //結(jié)構(gòu)化的方式查詢數(shù)據(jù) 

  2. Cursor data = db.query("contacts",new String[]{"id","name"},null,null,null,null,null); 

  3.  

  4. //結(jié)構(gòu)化方式插入數(shù)據(jù) 

  5. ContentValue values = new ContentValues(); 

  6. values.put("id",2); 

  7. values.put("name","cpacm"); 

  8. db.insert("table",null,values);

/** * 參數(shù)說(shuō)明 * table:數(shù)據(jù)表名,columns:需要顯示的列名,如果為null則相當(dāng)與* * selection:相當(dāng)于sql語(yǔ)句的where條件;selectionArgs數(shù)組放的是where條件要替換的?號(hào) * groupBy:SQL語(yǔ)句的Group, orderBy: 排序,默認(rèn)asc **/ public Cursor query (String table, String[] columns, String selection, String[] selectionArgs, String groupBy, String having, String orderBy){ }

比如說(shuō)我要查詢的SQL語(yǔ)句為

SELECT CustomerName, SUM(OrderPrice) FROM Orders WHERE Country=?        GROUP BY CustomerName        HAVING SUM(OrderPrice)>500  ORDER BY CustomerName

那么我寫的代碼如下

//數(shù)據(jù)表名 String table =  "Orders" ;   //要顯示的列名 String[] columns = new  String[] { "CustomerName" ,  "SUM(OrderPrice)" };   //選擇條件 String selection = "Country=?" ;   //里面的變量對(duì)應(yīng)條件中的問(wèn)號(hào),多個(gè)的時(shí)候請(qǐng)一一入座。 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);

這樣就能實(shí)現(xiàn)數(shù)據(jù)庫(kù)的查詢了。其它的語(yǔ)句參數(shù)都是差不多的,這里就不一一介紹了。

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)

課外小知識(shí):關(guān)于GroupBy和Having的使用
group  by  顧名思義就是按照xxx進(jìn)行分組,它必須有“聚合函數(shù)”來(lái)配合才能使用,使用時(shí)至少需要一個(gè)分組標(biāo)識(shí)字段。聚合函數(shù)有:sum()、count()、 avg()等,使用group  by目的就是要將數(shù)據(jù)分組進(jìn)行匯總操作。比如上面sql語(yǔ)句的CustomerName,如果它有四個(gè)行{“張三”,“李四”,“張三”,“李四”},那 么此時(shí)就會(huì)分成兩組,分別為張三組和李四組,然后統(tǒng)計(jì)出他們使用的orderprice總和。
HAVING作用就是為每一個(gè)組指定條件,像 where指定條件一樣,也就是說(shuō),可以根據(jù)你指定的條件來(lái)選擇行。如果你要使用HAVING子句的話,它必須處在GROUP  BY子句之后。還是上面的SQL語(yǔ)句,如果張三的SUM(OrderPrice)沒(méi)有超過(guò)500,那么張三組就不會(huì)顯示。

SQL語(yǔ)句的預(yù)編譯
在實(shí)踐中,有的SQL語(yǔ)句需要被反復(fù)使用,為了避免反復(fù)解析SQL語(yǔ)句產(chǎn)生的開(kāi)銷,可以對(duì)需要復(fù)用的SQL語(yǔ)句進(jìn)行預(yù)編譯,來(lái)提高數(shù)據(jù)庫(kù)操作的執(zhí)行效率。

//編譯復(fù)雜的SQL語(yǔ)句SQLiteStatement compiledSql = db.compileStatement(aSQL); //執(zhí)行SQLcompiledSql.execute();
//編譯復(fù)雜的SQL語(yǔ)句 SQLiteStatement compiledSql = db.compileStatement(aSQL); //執(zhí)行SQL compiledSql.execute();

課外小知識(shí):所謂事務(wù)是用戶定義的一 個(gè)數(shù)據(jù)庫(kù)操作序列,這些操作要么全做要么全不做,是一個(gè)不可分割的工作單位。例如,在關(guān)系數(shù)據(jù)庫(kù)中,一個(gè)事務(wù)可以是一條SQL語(yǔ)句、一組SQL語(yǔ)句或整個(gè) 程序。  簡(jiǎn)單舉個(gè)例子就是你要同時(shí)修改數(shù)據(jù)庫(kù)中兩個(gè)不同表的時(shí)候,如果它們不是一個(gè)事務(wù)的話,當(dāng)***個(gè)表修改完,可是第二表改修出現(xiàn)了異常而沒(méi)能修改的情況下,就 只有第二個(gè)表回到未修改之前的狀態(tài),而***個(gè)表已經(jīng)被修改完畢。  而當(dāng)你把它們?cè)O(shè)定為一個(gè)事務(wù)的時(shí)候,當(dāng)***個(gè)表修改完,可是第二表改修出現(xiàn)了異常而沒(méi)能修改的情況下,***個(gè)表和第二個(gè)表都要回到未修改的狀態(tài)!這就是所 謂的事務(wù)回滾。

SQLiteOpenHelper
在SQLiteOpenHelper中,封裝了一個(gè)SqliteDatabase對(duì)象,使用著可以通過(guò)使用此類來(lái)進(jìn)行數(shù)據(jù)庫(kù)的操作。

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的子類當(dāng)中,必須有該構(gòu)造函數(shù)       * @param context   上下文對(duì)象       * @param name      數(shù)據(jù)庫(kù)名稱       * @param factory       * @param version   當(dāng)前數(shù)據(jù)庫(kù)的版本,值必須是整數(shù)并且是遞增的狀態(tài)       */     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) {          // 數(shù)據(jù)庫(kù)***構(gòu)造時(shí),會(huì)調(diào)用該函數(shù),可以在這里構(gòu)造表、索引,等等          System.out.println("create a database");           //execSQL用于執(zhí)行SQL語(yǔ)句           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) {         // 如果給定的當(dāng)前數(shù)據(jù)庫(kù)版本高于已有數(shù)據(jù)庫(kù)版本,調(diào)用該函數(shù)         System.out.println("upgrade a database");     }    }

SQLiteOpenHelper的應(yīng)用
新建一個(gè)數(shù)據(jù)庫(kù)管理類DBManager

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;//用于操作數(shù)據(jù)庫(kù)的對(duì)象     private DBHelper dh = null;//用于創(chuàng)建數(shù)據(jù)庫(kù)的對(duì)象          private String dbName = "note.db";//數(shù)據(jù)庫(kù)的名稱     private int dbVersion = 1;//數(shù)據(jù)庫(kù)的版本     public DBManager(Context context){         mContext = context;     }      public void open(){         try{             dh = new DBHelper(mContext, dbName, null, dbVersion);//建立數(shù)據(jù)庫(kù)             if(dh == null){                 Log.v("msg", "is null");                 return ;             }             mSQLiteDatabase = dh.getWritableDatabase();//以可寫方式打開(kāi)數(shù)據(jù)庫(kù)             //dh.onOpen(mSQLiteDatabase);         }catch(SQLiteException se){             se.printStackTrace();         }     } public void close(){          mSQLiteDatabase.close();//關(guān)閉數(shù)據(jù)庫(kù)     dh.close();      } public Cursor selectAll(){     Cursor cursor = null;     try{         //sql語(yǔ)句操作         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語(yǔ)句操作         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{         //結(jié)構(gòu)化方式操作         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{         //結(jié)構(gòu)化方式操作         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{         //結(jié)構(gòu)化方式操作         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; }  }

獲取數(shù)據(jù)示例

private DBManager dm = null;// 數(shù)據(jù)庫(kù)管理對(duì)象 rivate Cursor cursor = null;            dm = new DBManager(this);//數(shù)據(jù)庫(kù)操作對(duì)象            dm.open();//打開(kāi)數(shù)據(jù)庫(kù)操作對(duì)象            cursor = dm.selectAll();//獲取所有數(shù)據(jù)            cursor.moveToFirst();//將游標(biāo)移動(dòng)到***條數(shù)據(jù),使用前必須調(diào)用                        int count = cursor.getCount();//個(gè)數(shù)            ArrayList<String> contents = new ArrayList<String>();//圖片的所有集合            ArrayList<String> imgs = new ArrayList<String>();//圖片的所有集合            ArrayList<String> items = new ArrayList<String>();//標(biāo)題的所有集合            ArrayList<String> times = new ArrayList<String>();//時(shí)間的所有集合            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();//將游標(biāo)指向下一個(gè)            }            dm.close();//關(guān)閉數(shù)據(jù)操作對(duì)象

數(shù)據(jù)庫(kù)的并發(fā)問(wèn)題
并發(fā)問(wèn)題是使用數(shù)據(jù)庫(kù)過(guò)程中最容易碰到的問(wèn)題,如果在開(kāi)發(fā)中碰到了android.database.SQLException異常,并提示"database is locked",那很有可能是出現(xiàn)了數(shù)據(jù)庫(kù)的死鎖導(dǎo)致無(wú)法訪問(wèn)。原因是Sqlite會(huì)對(duì)文件的讀寫進(jìn)行加鎖,防止數(shù)據(jù)被破壞。而在Android框架層SqliteDatabase會(huì)對(duì)所有數(shù)據(jù)庫(kù)對(duì)象進(jìn)行加鎖保護(hù),一旦出現(xiàn)了指向同一個(gè)數(shù)據(jù)庫(kù)的多個(gè)SqliteDatabase對(duì)象同時(shí)在多個(gè)線程中被使用,那就跳脫了SqliteDatabase鎖保護(hù),就會(huì)導(dǎo)致數(shù)據(jù)庫(kù)出現(xiàn)被鎖的異常。因此在實(shí)踐中,需要保證同時(shí)訪問(wèn)數(shù)據(jù)庫(kù)的SqliteDatabase對(duì)象僅有一個(gè)。(可以使用全局變量來(lái)保存數(shù)據(jù)庫(kù)對(duì)象,在整個(gè)數(shù)據(jù)源對(duì)象中使用同一個(gè)連接)
課外小知識(shí):在Android SDK中提供了工具Sqlite3,在shell模式下,可以對(duì)數(shù)據(jù)庫(kù)進(jìn)行增刪改查。  
cmd->adb shell ->sqlite3 <路徑>/<數(shù)據(jù)庫(kù)名> ->sqlite > select * from sqmple;

二、Android數(shù)據(jù)的云端服務(wù)

本質(zhì)上而言,云端存儲(chǔ)就是通過(guò)網(wǎng)絡(luò)將移動(dòng)設(shè)備上的數(shù)據(jù)存儲(chǔ)到遠(yuǎn)端服務(wù)器上。在Android中,增加了一些輔助功能,使得整個(gè)流程的實(shí)現(xiàn)變得更為簡(jiǎn)單。首先是通過(guò)Google賬號(hào)來(lái)標(biāo)識(shí)用戶身份。在android中,默認(rèn)支持使用Google賬號(hào)作為用戶身份的標(biāo)識(shí),系統(tǒng)上各個(gè)應(yīng)用都可以通過(guò)賬號(hào)系統(tǒng)獲得用戶的登錄信息。其次,有了Google賬號(hào),使得開(kāi)發(fā)者不需要自行構(gòu)建后臺(tái)服務(wù)系統(tǒng)。

Android的云端數(shù)據(jù)存取由系統(tǒng)服務(wù)BackupManagerService來(lái)統(tǒng)一管理。當(dāng)應(yīng)用提交備份數(shù)據(jù)請(qǐng)求時(shí),BackupManagerService會(huì)將該請(qǐng)求放入備份隊(duì)列中,該隊(duì)列會(huì)按照一定的控制邏輯定時(shí)提交到云端。當(dāng)有新應(yīng)用安裝到系統(tǒng)時(shí),會(huì)觸發(fā)數(shù)據(jù)恢復(fù)事件,BackupManagerService會(huì)憑借應(yīng)用包名和用戶賬號(hào)從云端取出相應(yīng)的備份數(shù)據(jù),嘗試恢復(fù)。

在實(shí)踐中,Android會(huì)構(gòu)造一個(gè)派生自BackupAgent類的子類android.app.backup.BackupAgentHelper的對(duì)象,來(lái)更方便地構(gòu)建云端存儲(chǔ)組件。

Android不會(huì)自行將數(shù)據(jù)提交到云端,開(kāi)發(fā)者需要顯性調(diào)用android.app.backup.BackupManager的dataChanged函數(shù)來(lái)觸發(fā)。

和所有組件一樣,云端存儲(chǔ)組件是由系統(tǒng)進(jìn)行托管的。這就需要把組件的相關(guān)信息放入配置文件中。

<application android:backupAgent = "MyBackupAgent"  ...>

以上就是“Android的數(shù)據(jù)庫(kù)怎么使用”這篇文章的所有內(nèi)容,感謝各位的閱讀!相信大家閱讀完這篇文章都有很大的收獲,小編每天都會(huì)為大家更新不同的知識(shí),如果還想學(xué)習(xí)更多的知識(shí),請(qǐng)關(guān)注億速云行業(yè)資訊頻道。

向AI問(wèn)一下細(xì)節(jié)

免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如果涉及侵權(quán)請(qǐng)聯(lián)系站長(zhǎng)郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。

AI