<本文学习郭神《第三行代码》总结>
SQLite是一种轻量级的关系型数据库,运算速度快,占用资源少,通常只需要几百KB。SQLite不仅支持标准的SQL语句,也遵循数据库的ACID事务。
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查看。
当如果继续添加一张新表,则需要使用到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时,则只创建新表,旧表不改变,当每一次数据库修改升级,都需要在这里进行版本判断的条件语句执行,才能保证数据库一直是最新状态。
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)
}
}
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更新,其他不更新。
SQLiteDatabase提供了方法delete用于数据删除,它接收三个参数:
(1)、表名
(2)、用于约束的条件名,和修改数据一样
(3)、用于约束的条件值,和修改数据一样
val helper = SQLiteHelper(this, "user.db", 2)
val db = helper.writableDatabase
db.delete("User", "age > ?", arrayOf("15"))
表示对age大于15的全部删除
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()
添加数据:
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)
在数据库操作过程中,进行增删改查的情况下,难免会出现异常等原因导致数据丢失,这时就需要使用到事务,比如进行数据替换时,要保证旧数据的删除和新数据的添加要一起完成,否则仍然保留旧数据,这样才能最大限度的避免数据的丢失。
开启事务需要调用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()
}