android 數據存儲之SQLite

使用嵌入式關係型SQLite數據庫存儲數據java

 

除了可使用文件或SharedPreferences存儲數據,還能夠選擇使用SQLite數據庫存儲數據。mysql

在Android平臺上,集成了一個嵌入式關係型數據庫—SQLite,android

一、SQLite3支持 NULL、INTEGER、REAL(浮點數字)、TEXT(字符串文本)和BLOB(二進制對象)數據類型,雖然它支持的類型雖然只有五種,但實際上sqlite3也接受varchar(n)、char(n)、decimal(p,s) 等數據類型,只不過在運算或保存時會轉成對應的五種數據類型。程序員

二、SQLite最大的特色是你能夠保存任何類型的數據到任何字段中,不管這列聲明的數據類型是什麼。例如:能夠在Integer字段中存放字符串,或者在布爾型字段中存放浮點數,或者在字符型字段中存放日期型值。sql

三、但有一種狀況例外:定義爲INTEGER PRIMARY KEY的字段只能存儲64位整數, 當向這種字段中保存除整數之外的數據時,將會產生錯誤。數據庫

四、另外, SQLite 在解析CREATE TABLE 語句時,會忽略 CREATE TABLE 語句中跟在字段名後面的數據類型信息,以下面語句會忽略 name字段的類型信息:數組

CREATE TABLE person (personid integer primary key autoincrement, name varchar(20))緩存

 

SQLite能夠解析大部分標準SQL語句,如:app

查詢語句:select * from 表名 where 條件子句 group by 分組字句 having ... order by 排序子句dom

如:select * from person

        select * from person order by id desc

        select name from person group by name having count(*)>1

分頁SQL與mysql相似,下面SQL語句獲取5條記錄,跳過前面3條記錄

select * from Account limit 5 offset 3 或者 select * from Account limit 3,5

插入語句:insert into 表名(字段列表) values(值列表)。如: insert into person(name, age) values(‘傳智’,3)

更新語句:update 表名 set 字段名=值 where 條件子句。如:update person set name=‘傳智‘ where id=10

刪除語句:delete from 表名 where 條件子句。如:delete from person  where id=10

 

使用SQLiteDatabase操做SQLite數據庫
Android提供了一個名爲SQLiteDatabase的類,該類封裝了一些操做數據庫的API。
能夠調用SQLiteDatabase的靜態方法:
public static SQLiteDatabase openDatabase(String path,SQLiteDatabase.CursorFactory factory,int flags)
 flags參數能夠是 OPEN_READWRITE, OPEN_READONLY ,CREATE_IF_NECESSARY, NO_LOCALIZED_COLLATORS四個的一個或多個(多個模式組合用|隔離).
public static SQLiteDatabase openOrCreateDatabase(File file,SQLiteDatabase.CursorFactory factory)
public static SQLiteDatabase openOrCreateDatabase(String path,SQLiteDatabase.CursorFactory factory)
來打開文件系統中位於絕對路徑path的數據庫。
還能夠經過Context對象調用
public abstract SQLiteDatabase openOrCreateDatabase(String name,int mode,SQLiteDatabase.CursorFactory factory)直接在私有數據庫目錄建立或打開一個名爲name的數據庫,
注意:mode只的是MODE_PRIVATE , MODE_WORLD_READABLE, MODE_WORLD_WRITEABLE。
Context還有:
public abstract String[] databaseList();//返回私有數據庫目錄全部數據庫名字
public abstract boolean deleteDatabase(String name);//刪除私有數據庫目錄內文件名爲name的數據庫。
除了在文件系統中建立SQLite數據庫,android還支持SQLite內存數據庫。在某些須要臨時建立數據庫,而且對操做速率相對要求高的狀況下,SQLite內存數據庫就發揮做用了,用SQLiteDatabase的靜態方法:
public static SQLiteDatabase create(SQLiteDatabase.CursorFactory factory)
來建立,建立失敗返回null。
最後記住,無論用何種方式打開了數據庫,得到的SQLite對象再也不使用時,都要調用close()來關閉打開的數據庫,不然拋出IllegalStateException異常。
使用SQLiteDatabase對象能夠完成對數據進行添加(Create)、查詢(Retrieve)、更新(Update)和刪除(Delete)操做(這些操做簡稱爲CRUD)。對SQLiteDatabase的學習,咱們應該重點掌握execSQL()和rawQuery()方法。 execSQL()方法能夠執行insert、delete、update和CREATE TABLE之類有更改行爲的SQL語句; rawQuery()方法能夠執行select語句。
execSQL()方法的使用例子:
SQLiteDatabase db = ....;
db.execSQL("insert into person(name, age) values('傳智播客', 4)");
db.close();
執行上面SQL語句會往person表中添加進一條記錄,在實際應用中, 語句中的「傳智播客」這些參數值應該由用戶輸入界面提供,若是把用戶輸入的內容原樣組拼到上面的insert語句, 當用戶輸入的內容含有單引號時,組拼出來的SQL語句就會存在語法錯誤。要解決這個問題須要對單引號進行轉義,也就是把單引號轉換成兩個單引號。有些時候用戶每每還會輸入像「 & 」這些特殊SQL符號,爲保證組拼好的SQL語句語法正確,必須對SQL語句中的這些特殊SQL符號都進行轉義,顯然,對每條SQL語句都作這樣的處理工做是比較煩瑣的。 SQLiteDatabase類提供了一個重載後的execSQL(String sql, Object[] bindArgs)方法,使用這個方法能夠解決前面提到的問題,由於這個方法支持使用佔位符參數(?)。使用例子以下:
SQLiteDatabase db = ....;
db.execSQL("insert into person(name, age) values(?,?)", new Object[]{"傳智播客", 4}); 
db.close();
execSQL(String sql, Object[] bindArgs)方法的第一個參數爲SQL語句,第二個參數爲SQL語句中佔位符參數的值,參數值在數組中的順序要和佔位符的位置對應。
SQLiteDatabase的rawQuery() 用於執行select語句,使用例子以下: SQLiteDatabase db = ....;
Cursor cursor = db.rawQuery(「select * from person」, null);
while (cursor.moveToNext()) {
int personid = cursor.getInt(0); //獲取第一列的值,第一列的索引從0開始
String name = cursor.getString(1);//獲取第二列的值
int age = cursor.getInt(2);//獲取第三列的值
}
cursor.close();
db.close(); 
rawQuery()方法的第一個參數爲select語句;第二個參數爲select語句中佔位符參數的值,若是select語句沒有使用佔位符,該參數能夠設置爲null。帶佔位符參數的select語句使用例子以下:
Cursor cursor = db.rawQuery("select * from person where name like ? and age=?", new String[]{"%傳智%", "4"});
 
Cursor是結果集遊標,用於對結果集進行隨機訪問,若是你們熟悉jdbc, 其實Cursor與JDBC中的ResultSet做用很類似。使用moveToNext()方法能夠將遊標從當前行移動到下一行,若是已經移過告終果集的最後一行,返回結果爲false,不然爲true。另外Cursor 還有經常使用的moveToPrevious()方法(用於將遊標從當前行移動到上一行,若是已經移過告終果集的第一行,返回值爲false,不然爲true )、moveToFirst()方法(用於將遊標移動到結果集的第一行,若是結果集爲空,返回值爲false,不然爲true )和moveToLast()方法(用於將遊標移動到結果集的最後一行,若是結果集爲空,返回值爲false,不然爲true ) 。
除了前面給你們介紹的execSQL()和rawQuery()方法, SQLiteDatabase還專門提供了對應於添加、刪除、更新、查詢的操做方法: insert()、delete()、update()和query() 。這些方法其實是給那些不太瞭解SQL語法的人使用的,對於熟悉SQL語法的程序員而言,直接使用execSQL()和rawQuery()方法執行SQL語句就能完成數據的添加、刪除、更新、查詢操做。
Insert()方法用於添加數據,各個字段的數據使用ContentValues進行存放。 ContentValues相似於MAP,相對於MAP,它提供了存取數據對應的put(String key, Xxx value)和getAsXxx(String key)方法,  key爲字段名稱,value爲字段值,Xxx指的是各類經常使用的數據類型,如:String、Integer等。
SQLiteDatabase db = databaseHelper.getWritableDatabase();
ContentValues values = new ContentValues();
values.put("name", "傳智播客");
values.put("age", 4);
long rowid = db.insert(「person」, null, values);//返回新添記錄的行號,與主鍵id無關
無論第三個參數是否包含數據,執行Insert()方法必然會添加一條記錄,若是第三個參數爲空,會添加一條除主鍵以外其餘字段值爲Null的記錄。Insert()方法內部實際上經過構造insert語句完成數據的添加,Insert()方法的第二個參數用於指定空值字段的名稱,相信你們對此參數會感到疑惑,此參數的做用是幹嗎的?是這樣的:若是第三個參數values 爲Null或者元素個數爲0, Insert()方法必然要添加一條除了主鍵以外其它字段爲Null值的記錄,爲了知足這條insert語句的語法, insert語句必須給定一個字段名,如:insert into person(name) values(NULL),假若不給定字段名 , insert語句就成了這樣: insert into person() values(),顯然這不知足標準SQL的語法。對於字段名,建議使用主鍵以外的字段,若是使用了INTEGER類型的主鍵字段,執行相似insert into person(personid) values(NULL)的insert語句後, 該主鍵字段值也不會爲NULL。若是第三個參數values 不爲Null而且元素的個數大於0 ,能夠把第二個參數設置爲null。
delete()方法的使用:
SQLiteDatabase db = databaseHelper.getWritableDatabase();
db.delete("person", "personid<?", new String[]{"2"});
db.close();
上面代碼用於從person表中刪除personid小於2的記錄。
 
update()方法的使用:
SQLiteDatabase db = databaseHelper.getWritableDatabase();
ContentValues values = new ContentValues();
values.put(「name」, 「傳智播客」);//key爲字段名,value爲值
db.update("person", values, "personid=?", new String[]{"1"}); 
db.close();
上面代碼用於把person表中personid等於1的記錄的name字段的值改成「傳智播客」。
query()方法其實是把select語句拆分紅了若干個組成部分,而後做爲方法的輸入參數:
SQLiteDatabase db = databaseHelper.getWritableDatabase();
Cursor cursor = db.query("person", new String[]{"personid,name,age"}, "name like ?", new String[]{"%溧陽%"}, null, null, "personid desc", "1,2");
while (cursor.moveToNext()) {
         int personid = cursor.getInt(0); //獲取第一列的值,第一列的索引從0開始
        String name = cursor.getString(1);//獲取第二列的值
        int age = cursor.getInt(2);//獲取第三列的值
}
cursor.close();
db.close(); 
上面代碼用於從person表中查找name字段含有「傳智」的記錄,匹配的記錄按personid降序排序,對排序後的結果略過第一條記錄,只獲取2條記錄。
query(table, columns, selection, selectionArgs, groupBy, having, orderBy, limit)方法各參數的含義:
table:表名。至關於select語句from關鍵字後面的部分。若是是多表聯合查詢,能夠用逗號將兩個表名分開。
columns:要查詢出來的列名。至關於select語句select關鍵字後面的部分。
selection:查詢條件子句,至關於select語句where關鍵字後面的部分,在條件子句容許使用佔位符「?」
selectionArgs:對應於selection語句中佔位符的值,值在數組中的位置與佔位符在語句中的位置必須一致,不然就會有異常。
groupBy:至關於select語句group by關鍵字後面的部分
having:至關於select語句having關鍵字後面的部分
orderBy:至關於select語句order by關鍵字後面的部分,如:personid desc, age asc;
limit:指定偏移量和獲取的記錄數,至關於select語句limit關鍵字後面的部分。
 
使用SQLiteOpenHelper對數據庫進行版本管理
若是應用使用到了SQLite數據庫,在用戶初次使用軟件時,須要建立應用使用到的數據庫表結構及添加一些初始化記錄,另外在軟件升級的時候,也須要對數據表結構進行更新。在Android系統,爲咱們提供了一個名爲SQLiteOpenHelper的類,該類用於對數據庫版本進行管理,該類是一個抽象類,必須繼承它才能使用。 爲了實現對數據庫版本進行管理,SQLiteOpenHelper類有兩種重要的方法,分別是onCreate(SQLiteDatabase db)和onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion)。還能夠實現public abstract void onUpgrade(SQLiteDatabase db,int oldVersion,int newVersion)方法,它在每次成功打開數據庫後首先被執行,默認狀況下此方法的實現爲空。
 
當調用SQLiteOpenHelper的getWritableDatabase()或者getReadableDatabase()方法獲取用於操做數據庫的SQLiteDatabase實例的時候,若是數據庫不存在,Android系統會自動生成一個數據庫,接着調用onCreate()方法,onCreate()方法在初次生成數據庫時纔會被調用,在onCreate()方法裏能夠生成數據庫表結構及添加一些應用使用到的初始化數據。onUpgrade()方法在數據庫的版本發生變化時會被調用,數據庫的版本是由程序員控制的,假設數據庫如今的版本是1,因爲業務的須要,修改了數據庫表的結構,這時候就須要升級軟件,升級軟件時但願更新用戶手機裏的數據庫表結構,爲了實現這一目的,能夠把原來的數據庫版本設置爲2(有同窗問設置爲3行不行?固然能夠,若是你願意,設置爲100也行),而且在onUpgrade()方法裏面實現表結構的更新。當軟件的版本升級次數比較多,這時在onUpgrade()方法裏面能夠根據原版號和目標版本號進行判斷,而後做出相應的表結構及數據更新。
 
getWritableDatabase()和getReadableDatabase()方法均可以獲取一個用於操做數據庫的SQLiteDatabase實例。但getWritableDatabase() 方法以讀寫方式打開數據庫,一旦數據庫的磁盤空間滿了,數據庫就只能讀而不能寫,假若使用的是getWritableDatabase() 方法就會出錯。getReadableDatabase()方法先以讀寫方式打開數據庫,若是數據庫的磁盤空間滿了,就會打開失敗,當打開失敗後會繼續嘗試以只讀方式打開數據庫。但若隨後再次調用此方法時,問題已經被解決,只讀的SQLiteDatabase對象會被關閉,而從新返回一個可讀寫的SQLiteDatabase數據庫對象。
public class DatabaseHelper extends SQLiteOpenHelper {
    //類沒有實例化,是不能用做父類構造器的參數,必須聲明爲靜態
         private static final String name = "itcast"; //數據庫名稱
         private static final int version = 1; //數據庫版本
         public DatabaseHelper(Context context) {
//第三個參數CursorFactory指定在執行查詢時得到一個遊標實例的工廠類,設置爲null,表明使用系統默認的工廠類
                super(context, name, null, version);
         }
        @Override public void onCreate(SQLiteDatabase db) {
              db.execSQL("CREATE TABLE IF NOT EXISTS person (personid integer primary key autoincrement, name varchar(20), age INTEGER)");   
         }
        @Override public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
               db.execSQL("DROP TABLE IF EXISTS person");
               onCreate(db);
         }
}
上面onUpgrade()方法在數據庫版本每次發生變化時都會把用戶手機上的數據庫表刪除,而後再從新建立。通常在實際項目中是不能這樣作的,正確的作法是在更新數據庫表結構時,還要考慮用戶存放於數據庫中的數據不會丟失。
 
使用SQLiteOpenHelper獲取用於操做數據庫的SQLiteDatabase實例
public class DatabaseHelper extends SQLiteOpenHelper {
         private static final String name = "itcast"; //數據庫名稱
         private static final int version = 1; //數據庫版本
         ......略
}
public class HelloActivity extends Activity {
    @Override public void onCreate(Bundle savedInstanceState) {
        ......
        Button button =(Button) this.findViewById(R.id.button);
        button.setOnClickListener(new View.OnClickListener(){
public void onClick(View v) {
DatabaseHelper databaseHelper = new DatabaseHelper(HelloActivity.this);
SQLiteDatabase db = databaseHelper.getWritableDatabase();
db.execSQL("insert into person(name, age) values(?,?)", new Object[]{"傳智播客", 4});
db.close();  
}});        
    }
}
第一次調用getWritableDatabase()或getReadableDatabase()方法後,SQLiteOpenHelper會緩存當前的SQLiteDatabase實例,SQLiteDatabase實例正常狀況下會維持數據庫的打開狀態,因此在你再也不須要SQLiteDatabase實例時,請及時調用close()方法釋放資源。一旦SQLiteDatabase實例被緩存,屢次調用getWritableDatabase()或getReadableDatabase()方法獲得的都是同一實例。
 
使用事務操做SQLite數據庫
使用SQLiteDatabase的beginTransaction()方法能夠開啓一個事務,程序執行到endTransaction() 方法時會檢查事務的標誌是否爲成功,若是爲成功則提交事務,不然回滾事務。當應用須要提交事務,必須在程序執行到endTransaction()方法以前使用setTransactionSuccessful() 方法設置事務的標誌爲成功,若是不調用setTransactionSuccessful() 方法,默認會回滾事務。使用例子以下: SQLiteDatabase db = ....;
db.beginTransaction();//開始事務
try {
    db.execSQL("insert into person(name, age) values(?,?)", new Object[]{"傳智播客", 4});
    db.execSQL("update person set name=? where personid=?", new Object[]{"傳智", 1});
    db.setTransactionSuccessful();//調用此方法會在執行到endTransaction() 時提交當前事務,若是不調用此方法會回滾事務
} finally {
    db.endTransaction();//由事務的標誌決定是提交事務,仍是回滾事務
db.close(); 
上面兩條SQL語句在同一個事務中執行。
SQLite示例程序

   1.建立Android工程

       Project name: db

       BuildTarget:Android2.2

       Application name: 數據庫應用

       Package name: com.jbridge.db

       Create Activity: DBActivity

       Min SDK Version:八、

 2. Person實體

 

package com.jbridge.domain;

import android.R.string;

public class Person {
	private Integer id;
	private String name;
	private Short age;

	public Person(String name, Short age) {
		this.name = name;
		this.age = age;
	}

	public Person(Integer id, String name, Short age) {
		super();
		this.id = id;
		this.name = name;
		this.age = age;
	}

	public Integer getId() {
		return id;
	}

	public void setId(Integer id) {
		this.id = id;
	}

	public String getName() {
		return name;
	}

	public void setName(String name) {
		this.name = name;
	}

	public Short getAge() {
		return age;
	}

	public void setAge(Short age) {
		this.age = age;
	}

	@Override
	public String toString() {
		return "Person [id=" + id + ", name=" + name + ", age=" + age + "]";
	}

}

 

  3.編寫DataBaseOpenHelper類

      DataBaseOpenHelper繼承自SQLiteOpenHelper類。咱們須要建立數據表,必須重寫onCreate(更新時重寫onUpgrade方法)方法,在這個方法中建立數據表。

package com.jbridge.service;

import android.content.Context;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteDatabase.CursorFactory;
import android.database.sqlite.SQLiteOpenHelper;

public class DataBaseOpenHelper extends SQLiteOpenHelper {
	// 類沒有實例化,是不能用做父類構造器的參數,必須聲明爲靜態
	private static String dbname = "zyj";
	private static int version = 1;

	public DataBaseOpenHelper(Context context) {
		// 第一個參數是應用的上下文
		// 第二個參數是應用的數據庫名字
		// 第三個參數CursorFactory指定在執行查詢時得到一個遊標實例的工廠類,設置爲null,表明使用系統默認的工廠類
		// 第四個參數是數據庫版本,必須是大於0的int(即非負數)
		super(context, dbname, null, version);
		// TODO Auto-generated constructor stub
	}

	public DataBaseOpenHelper(Context context, String name,
			CursorFactory factory, int version) {
		super(context, name, factory, version);
		// TODO Auto-generated constructor stub
	}

	@Override
	public void onCreate(SQLiteDatabase db) {
		db.execSQL("CREATE TABLE IF NOT EXISTS person (personid integer primary key autoincrement, name varchar(20), age INTEGER)");
	}

	// onUpgrade()方法在數據庫版本每次發生變化時都會把用戶手機上的數據庫表刪除,而後再從新建立。
	// 通常在實際項目中是不能這樣作的,正確的作法是在更新數據庫表結構時,還要考慮用戶存放於數據庫中的數據不會丟失,從版本幾更新到版本幾。
	@Override
	public void onUpgrade(SQLiteDatabase db, int arg1, int arg2) {
		db.execSQL("DROP TABLE IF EXISTS person");
		onCreate(db);
	}

}

 4.編寫PersonService類

      PersonService類主要實現對業務邏輯和數據庫的操做

 

package com.jbridge.service;

import java.util.ArrayList;
import java.util.Currency;
import java.util.List;

import android.content.Context;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;

import com.jbridge.domain.Person;

public class PersonService {

	private DataBaseOpenHelper dbOpenHelper;

	// private Context context;

	public PersonService(Context context) {
		// this.context = context;
		dbOpenHelper = new DataBaseOpenHelper(context);
	}

	public void save(Person person) {
		SQLiteDatabase database = dbOpenHelper.getWritableDatabase();
		database.beginTransaction();
		database.execSQL("insert into person(name,age)values(?,?)",
				new Object[] { person.getName(), person.getAge() });
		// database.close();能夠不關閉數據庫,他裏面會緩存一個數據庫對象,若是之後還要用就直接用這個緩存的數據庫對象。但經過
		// context.openOrCreateDatabase(arg0, arg1, arg2)打開的數據庫必須得關閉
		database.setTransactionSuccessful();
		database.endTransaction();

	}

	public void update(Person person) {
		SQLiteDatabase database = dbOpenHelper.getWritableDatabase();
		database.execSQL(
				"update person set name=?,age=? where personid=?",
				new Object[] { person.getName(), person.getAge(),
						person.getId() });
	}

	public Person find(Integer id) {
		SQLiteDatabase database = dbOpenHelper.getReadableDatabase();
		Cursor cursor = database.rawQuery(
				"select * from person where personid=?",
				new String[] { String.valueOf(id) });
		if (cursor.moveToNext()) {
			return new Person(cursor.getInt(0), cursor.getString(1),
					cursor.getShort(2));
		}
		return null;
	}

	public void delete(Integer... ids) {
		if (ids.length > 0) {
			StringBuffer sb = new StringBuffer();
			for (Integer id : ids) {
				sb.append('?').append(',');
			}
			sb.deleteCharAt(sb.length() - 1);
			SQLiteDatabase database = dbOpenHelper.getWritableDatabase();
			database.execSQL(
					"delete from person where personid in(" + sb.toString()
							+ ")", ids);
		}
	}

	public List<Person> getScrollData(int startResult, int maxResult) {
		List<Person> persons = new ArrayList<Person>();
		SQLiteDatabase database = dbOpenHelper.getReadableDatabase();
		Cursor cursor = database.rawQuery(
				"select * from person limit ?,?",
				new String[] { String.valueOf(startResult),
						String.valueOf(maxResult) });
		while (cursor.moveToNext()) {
			persons.add(new Person(cursor.getInt(0), cursor.getString(1),
					cursor.getShort(2)));
		}
		return persons;
	}

	// 獲取分頁數據,提供給SimpleCursorAdapter使用。
	public Cursor getRawScrollData(int startResult, int maxResult) {
		List<Person> persons = new ArrayList<Person>();
		SQLiteDatabase database = dbOpenHelper.getReadableDatabase();
		return database.rawQuery(
				"select personid as _id ,name,age from person limit ?,?",
				new String[] { String.valueOf(startResult),
						String.valueOf(maxResult) });

	}

	public long getCount() {
		SQLiteDatabase database = dbOpenHelper.getReadableDatabase();
		Cursor cursor = database.rawQuery("select count(*) from person", null);
		if (cursor.moveToNext()) {
			return cursor.getLong(0);
		}
		return 0;
	}

}

  下面是使用 insert()、delete()、update()和query()方法實現的業務類

package com.jbridge.service;

import java.util.ArrayList;
import java.util.Currency;
import java.util.List;

import android.R.string;
import android.content.ContentValues;
import android.content.Context;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;

import com.jbridge.domain.Person;

public class OtherPersonService {

	private DataBaseOpenHelper dbOpenHelper;

	// private Context context;

	public OtherPersonService(Context context) {
		// this.context = context;
		dbOpenHelper = new DataBaseOpenHelper(context);
	}

	public void save(Person person) {
		SQLiteDatabase database = dbOpenHelper.getWritableDatabase();
		ContentValues contentValues = new ContentValues();
		contentValues.put("name", person.getName());
		contentValues.put("age", person.getAge());
		database.insert("person", null, contentValues);
	}

	public void update(Person person) {
		SQLiteDatabase database = dbOpenHelper.getWritableDatabase();
		ContentValues contentValues = new ContentValues();
		contentValues.put("name", person.getName());
		contentValues.put("age", person.getAge());
		database.update("person", null, "personid=?",
				new String[] { String.valueOf(person.getId()) });
	}

	public Person find(Integer id) {
		SQLiteDatabase database = dbOpenHelper.getReadableDatabase();
		Cursor cursor = database.query("person", new String[] { "personid",
				"name", "age" }, "personid=?",
				new String[] { String.valueOf(id) }, null, null, null);
		if (cursor.moveToNext()) {
			return new Person(cursor.getInt(0), cursor.getString(1),
					cursor.getShort(2));
		}
		return null;
	}

	public void delete(Integer... ids) {
		if (ids.length > 0) {
			StringBuffer sb = new StringBuffer();
			String[] strIds = new String[ids.length];
			// for (Integer id : ids) {
			// sb.append('?').append(',');
			// }
			for (int i = 0; i < strIds.length; i++) {
				sb.append('?').append(',');
				strIds[i] = String.valueOf(ids[i]);
			}
			sb.deleteCharAt(sb.length() - 1);
			SQLiteDatabase database = dbOpenHelper.getWritableDatabase();
			database.delete("person", "personid in(" + sb.toString() + ")",
					strIds);
		}
	}

	public List<Person> getScrollData(int startResult, int maxResult) {
		List<Person> persons = new ArrayList<Person>();
		SQLiteDatabase database = dbOpenHelper.getReadableDatabase();
		Cursor cursor = database.query("person", new String[] { "personid",
				"name", "age" }, null, null, null, null, "personid desc",
				startResult + "," + maxResult);
		while (cursor.moveToNext()) {
			persons.add(new Person(cursor.getInt(0), cursor.getString(1),
					cursor.getShort(2)));
		}
		return persons;
	}

	public long getCount() {
		SQLiteDatabase database = dbOpenHelper.getReadableDatabase();
		Cursor cursor = database.query("person", new String[] { "count(*)" },
				null, null, null, null, null);
		if (cursor.moveToNext()) {
			return cursor.getLong(0);
		}
		return 0;
	}

}

   5.編寫測試類

       編寫一個針對PersonService的測試類,測試PersonService類中的各個方法是否正確

package com.jbridge.db;

import java.util.List;

import com.jbridge.domain.Person;
import com.jbridge.service.OtherPersonService;
import com.jbridge.service.PersonService;

import android.test.AndroidTestCase;
import android.util.Log;

public class PersonServiceTest extends AndroidTestCase {
	private static String TAG = "PersonServiceTest";

	// OtherPersonService personService = new
	// OtherPersonService(this.getContext());
	// //不能夠這麼寫,由於Android把context環境變量是在PersonServiceTest實例化後給他的

	public void testSave() throws Exception {
		PersonService personService = new PersonService(this.getContext());
		// personService.save(new Person("老豬", (short) 11));
		for (int i = 0; i < 10; i++) {
			personService.save(new Person("你" + i, (short) (i + 10)));
		}

	}

	public void testFind() throws Exception {
		PersonService personService = new PersonService(this.getContext());
		Person person = personService.find(1);
		Log.i(TAG, person.toString());
	}

	public void testUpdate() throws Exception {
		PersonService personService = new PersonService(this.getContext());
		Person person = personService.find(1);
		person.setName("lv");
		personService.update(person);
	}

	public void testDelete() throws Exception {
		PersonService personService = new PersonService(this.getContext());
		personService.delete(1, 2, 3);
	}

	public void testGetCount() throws Exception {
		PersonService personService = new PersonService(this.getContext());
		Log.i(TAG, String.valueOf(personService.getCount()));
	}

	public void testGetScrollData() throws Exception {
		PersonService personService = new PersonService(this.getContext());
		List<Person> persons = personService.getScrollData(0, 3);
		for (Person person : persons) {
			Log.i(TAG, person.toString());
		}
	}
}
相關文章
相關標籤/搜索