<本文學習郭神《第三行代碼》總結>
3.SQLite數據庫存儲
SQLite是一種輕量級的關係型數據庫,運算速度快,佔用資源少,通常只需要幾百KB。SQLite不僅支持標準的SQL語句,也遵循數據庫的ACID事務。
- 3.1創建數據庫
Android提供了一個SQLiteOpenHelper幫助類,通過它可以實現對數據庫的創建和升級。
SQLiteOpenHelper是一個抽象類,在使用時,需要自定義工具類去繼承它。SQLiteOpenHelper兩個抽象方法:onCreate、onUpgrade,必須要重寫。
SQLiteOpenHelper兩個實例方法:getReadableDatabase()、getWritableDatabase()。這兩個方法都可以創建和打開數據庫,並返回一個可對數據庫進行操作的對象。當數據庫不可寫入時,getReadableDatabase()方法返回的對象將以只讀的方式打開,getWritableDatabase()則會出現異常。
SQLiteOpenHelper兩個構造方法:一般使用接收四個參數方法:
(1)、Context
(2)、數據庫名
(3)、允許查詢數據的時候返回一個自定義的Cursor,一般出入null
(4)、數據庫版本號
構建SQLiteOpenHelper的實例之後,再調用getReadableDatabase()或getWritableDatabase()方法就能夠創建數據庫,數據庫默認路徑存放data/data//database/目錄。
比如創建一個用戶表:
class SQLiteHelper(
context: Context,
name: String,
version: Int
) : SQLiteOpenHelper(context, name, null, version) {
private val createUser = "create table User (" +
"id integer primary key autoincrement," +
"name text," +
"age integer," +
"sex text" +
")"
override fun onCreate(db: SQLiteDatabase) {
db.execSQL(createUser)
}
override fun onUpgrade(db: SQLiteDatabase, p1: Int, p2: Int) {
TODO("not implemented") //To change body of created functions use File | Settings | File Templates.
}
}
建表語句定義成一個字符串變量,然後再onCreate中調用SQLiteDatabase的execSQL方法執行建表語句,然後再Activity中調用。
class SQLActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
val helper = SQLiteHelper(this, "user.db", 1)
helper.writableDatabase
}
}
此時,user.db數據庫和user表創建成功。查看創建成功表,在Device File Explorer中找到db文件,然後使用SQL軟件查看,或者使用插件Database Navigator查看。
- 3.2、數據庫升級
當如果繼續添加一張新表,則需要使用到onUpgrade方法。
比如再添加一張car表:
class SQLiteHelper(
context: Context,
name: String,
version: Int
) : SQLiteOpenHelper(context, name, null, version) {
private val createUser = "create table User (" +
"id integer primary key autoincrement," +
"name text," +
"age integer," +
"sex text" +
")"
private val createCar = "create table Car (" +
"id integer primary key autoincrement," +
"name text," +
"vin text," +
"color text" +
")"
override fun onCreate(db: SQLiteDatabase) {
db.execSQL(createUser)
db.execSQL(createCar)
}
override fun onUpgrade(db: SQLiteDatabase, oldVersion: Int, newVersion: Int) {
db.execSQL("drop table if exists User")
db.execSQL("drop table if exists Car")
onCreate(db)
}
}
在onUpgrade方法中執行DROP語句,當存在這兩張表時,就刪除,重新創建。
接下來在Activity中調用時,就需要把版本號升級。
class SQLActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
val helper = SQLiteHelper(this, "user.db", 2)
helper.writableDatabase
}
}
如果不能刪除之前已經創建的表,則需要進行條件判斷,創建表,那麼onUpgrade方法就可以修改爲:
override fun onUpgrade(db: SQLiteDatabase, oldVersion: Int, newVersion: Int) {
if (oldVersion <= 1) {
db.execSQL(createCar)
}
}
當檢測到舊版本爲1時,則只創建新表,舊錶不改變,當每一次數據庫修改升級,都需要在這裏進行版本判斷的條件語句執行,才能保證數據庫一直是最新狀態。
- 3.3、添加數據
SQLiteDatabase提供了方法insert用於數據添加,它接收三個參數:
(1)、表名
(2)、用於在未指定添加數據的情況下給某些可爲空的列自動賦值NULL
(3)、ContentValues對象,提供一系列put方法重載,用於向ContentValues中添加數據,只需將表中的每個列名以及相應的待添加數據傳入即可。
class SQLActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
val helper = SQLiteHelper(this, "user.db", 2)
val db = helper.writableDatabase
val value1 = ContentValues().apply {
put("name", "Tom")
put("age", 11)
put("sex", "male")
}
db.insert("User", null, value1)
val value2 = ContentValues().apply {
put("name", "BMW")
put("VIN", "GSZK25948028783749")
put("color", "red")
}
db.insert("Car", null, value2)
}
}
- 3.4、更新數據
SQLiteDatabase提供了方法updata用於數據修改,它接收三個參數:
(1)、表名
(2)、ContentValues對象,提供一系列put方法重載,用於向ContentValues中添加數據,只需將表中要修改的列名以及相應的待添加數據傳入即可。
(3)、用於約束的條件名,對應SQL語句的where部分,表示更新某一個指定條件列。
(4)、用於約束的條件值,提供一個字符串數據爲第三個參數的條件列賦值,表示將第三個參數中的列名的所對應的第四個參數的列值所對應的數據進行更新,其他的不更新。
注意:第三、四參數用於約束某一行或某幾行的數據,如果不指定,則修改所有數據。
val helper = SQLiteHelper(this, "user.db", 2)
val db = helper.writableDatabase
val value = ContentValues()
value.put("age", 16)
db.update("User", value, "name = ?", arrayOf("Tom"))
這裏就只對name爲Tom的行數據,age更新,其他不更新。
- 3.5、刪除數據
SQLiteDatabase提供了方法delete用於數據刪除,它接收三個參數:
(1)、表名
(2)、用於約束的條件名,和修改數據一樣
(3)、用於約束的條件值,和修改數據一樣
val helper = SQLiteHelper(this, "user.db", 2)
val db = helper.writableDatabase
db.delete("User", "age > ?", arrayOf("15"))
表示對age大於15的全部刪除
- 3.6、查詢數據
SQLiteDatabase提供了方法query用於數據查詢,它接收七個參數:
(1)、表名
(2)、查詢哪幾列,不指定則查詢所有
(3)、用於約束的條件名
(4)、用於約束的條件值
(5)、指定需要groupby的列,不指定則不對查詢結果進行groupby操作
(6)、查詢完數據進行過濾,不指定則不過濾
(7)、排序,不指定則使用默認方式排序
val helper = SQLiteHelper(this, "user.db", 2)
val db = helper.writableDatabase
val cursor = db.query("User", null, null, null, null, null, "age")
if (cursor.moveToFirst()){
do {
val name = cursor.getString(cursor.getColumnIndex("name"))
val age = cursor.getInt(cursor.getColumnIndex("age"))
val sex = cursor.getString(cursor.getColumnIndex("sex"))
} while (cursor.moveToNext())
}
cursor.close()
- 3.7、也可以直接使用SQL語句實現上述的增刪改查
添加數據:
db.execSQL(“insert into User(name, age, sex) values (?, ?, ?)”, arrayOf(“Tom”, 11, “male”))
更新數據:
db.execSQL(“update User set age = ? where name = ?”, arrayOf(16, “Tom”))
刪除數據:
db.execSQL(“delete from User where age > ?”, arrayOf(15))
查詢數據:
db.rawQuery(“select * from User”, null)
- 3.8、開啓事務
在數據庫操作過程中,進行增刪改查的情況下,難免會出現異常等原因導致數據丟失,這時就需要使用到事務,比如進行數據替換時,要保證舊數據的刪除和新數據的添加要一起完成,否則仍然保留舊數據,這樣才能最大限度的避免數據的丟失。
開啓事務需要調用beginTransaction方法,通過setTransactionsuccful方法表示事務成功,endTransaction方法結束事務。
val helper = SQLiteHelper(this, "user.db", 2)
val db = helper.writableDatabase
db.beginTransaction()
try {
db.delete("User", null, null)
val values = ContentValues().apply {
put("name", "Android")
put("age", 100)
put("sex", "male")
}
db.insert("User", null, values)
db.setTransactionSuccessful()
} catch (e: Exception){
e.printStackTrace()
} finally {
db.endTransaction()
}