赞
踩
参考 《第一行代码 第三版》教程
Android 内置了SQLite数据库
SQLite 是一款轻量级的关系型数据库,运算速度快,占用资源少,支持标准SQL语法,数据库ACID事务,可以用于记录复杂的关系性数据
SQLiteOpenHelper是一个抽象类,需要继承它,实现两个抽象方法 onCreate()
和 onUpgrade()
, 在这两个方法创建和升级数据库
SQLiteOpenHelper 具有两个重要的实例方法: getReadableDatabase()
和 getWritableDatabase()
, 两个方法都可以创建或打开现有数据库(如果数据库已存在则直接打开,否则要创建一个新的数据库),并返回读写操作对象。当数据库不可写(磁盘已满)时, getReadableDatabase()以只读方式打开数据库, getWritbaleDatabase() 出现异常
SQLiteOpenHelper 有两个构造方法可供重写, 一般重写参数少的那个即可
接受4个参数:
Context: 操作数据库
数据库名: 创建数据库时的名称
Cursor: 运行查询数据库是返回一个Cursor,一般传入null
当前数据库版本号:用于数据库升级
构建SQLiteOpenHelper之后,调用getReadableDatabase() 或 getWritableDatabase() 后创建数据库
存放目录: /data/data/<package name>/databases/
案例: 新建Book表, 有id(主键)、作者、价格、页数、书名列
建表语句:
create table Book (
id integer primary key autoincrement,
author text,
price real,
pages integer,
name text)
integer表示整型,real表示浮点型,text表示文本类型,blob表示二进制类型。
primary key 主键
autoincrement 自增长
建表代码:
class MyDatabaseHelper(val context: Context, name: String, version: Int) : SQLiteOpenHelper(context, name, null, version) { private val createBook = "create table Book (" + " id integer primary key autoincrement," + "author text," + "price real," + "pages integer," + "name text)" override fun onCreate(db: SQLiteDatabase) { db.execSQL(createBook) // 执行SQL Toast.makeText(context, "Success", Toast.LENGTH_SHORT).show() } override fun onUpgrade(db: SQLiteDatabase, oldVersion: Int, newVersion: Int) { } }
新建一个createDatabase 按钮
在onCreate() 方法中构建一个MyDatabaseHelper对象, 点击时调用getWritableDatabase() 方法
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceStanceState)
...
val dbHelper = MyDatabaseHelper(this, "BookStore.db", 1)
createDatbase.setOnClickListener {
dbHelper.writeableDatabase
}
}
点击后会创建数据,再次点击不会重新创建一次
将 /data/data/com.e xample.databasetest/databases/
下的数据库保存到电脑中
然后使用Database Navigator
插件来查看数据库,
双击Book表,然后点击no filter
查看表内容
private val createCategory = "create table Category (" +
"id integer primary key autoincrement," +
"category_name text," +
"category_code integer)"
override fun onCreate(db: SQLiteDatabase) {
db.execSQL(createBook)
db.execSQL(createCategory)
Toast.makeText(context, "Create succeeded", Toast.LENGTH_SHORT).show()
}
但是没有新建成功,
在 onUpgrade
中执行drop语句:
override fun onUpgrade(db: SQLiteDatabase, oldVersion: Int, newVersion: Int) {
db.execSQL("drop table if exists Book")
db.execSQL("drop table if exists Category")
onCreate(db)
}
如何执行 onUpgrade()
方法?
需要传入版本号,要比之前的大
val dbHelper = MyDatabaseHelper(this, "BookStore.db", 2)
createDatabase.setOnClickListener {
dbHelper.writableDatabase
}
CRUD(增查改删) : create添加 retrieve查询 update更新 delete删除
getReadableDatabase 和 getWritableDatabase 用于创建、升级数据库, 会返回一个SQLiteDatabase对象, 借助这个对象CRUD
实例,新建addDate按钮:
addData.setOnClickLisener {
val db = dbHelper.writeableDatabase
val values1 = ContentValues().apply {
put("name", "first line code")
put("author", "guolin")
put("pages", 100)
put("price", 16)
}
db.insert("Book", null, values1)
}
更新书本价格:
updateData.setOnClickListener {
val db = dbHelper.writeableDatabase
val values = ContentValues()
values.put("price", 10)
db.update("Book", values, "name=?", arrayOf("first line code"))
}
daleteData.setOnClickListener {
val db = dbHelper.writableDatabase
db.delete("Book", "pages > ?", arrayOf("500"))
}
第二个 参数用于指定去查询哪几列,如果不指定则默认查询所有列。
第三、第四个参数用于约束查询某一行或某几行的数据,不指定则默认查询所有行的数据。第五个参数用于指定需要去group by 的列,不指定则表示不对查询结果进行group by 操作。
第六个参数用于对group by 之后的数据进行进一步的过滤,不指定则表示不进行过滤。
第七个参数用于指定查询结果的排序方式,不指定则表示使用默认的排序方式。
调用query() 方法后会返回一个Cursor对象, 查询到的数据将从这个对象取出
queryData.setOnClickListener { val db = dbHelper.writableDatabase // 查询Book表中所有的数据 val cursor = db.query("Book", null, null, null, null, null, null) if (cursor.moveToFirst()) { do { // 遍历Cursor对象,取出数据并打印 val name = cursor.getString(cursor.getColumnIndexOrThrow("name")) val author = cursor.getString(cursor.getColumnIndexOrThrow("author")) val pages = cursor.getInt(cursor.getColumnIndexOrThrow("pages")) val price = cursor.getDouble(cursor.getColumnIndexOrThrow("price")) Log.d("MainActivity", "book name is $name") Log.d("MainActivity", "book author is $author") Log.d("MainActivity", "book pages is $pages") Log.d("MainActivity", "book price is $price") } while (cursor.moveToNext()) } cursor.close() }
调用query方法后,返回一个Cursor对象
调用moveToFirst(), 将指针移到第一行, 进入一个循环,遍历查询每行数据
通过Cursor的getColumnIndexOrThrow() 方法获取某一列在表中对应的位置索引,然后使用 cursor.getString 方法取出值
最后使用close方法来关闭Cursor()
直接执行SQL语句查询
(1)添加数据:
db.execSQL(“insert into Book (name, author, pages, price) values(?,?,?,?)”, arrayOf(“fist line code”, “guolin”, “100”, “66”))
(2)更新数据
db.execSQL(“update Book set price = ? where name = ?”, arrayOf(“10.99”, “The Da Vinci Code”))
(3)删除数据
db.execSQL(“delete from Book where pages > ?”, arrayOf(“500”))
(4)查询数据
val cursor = db.rawQuery(“select * from Book”, null)
查询使用rawQuery()方法,
其他操作都是调用的execSQL()方法。
使用事务
保证多个操作一起成功或者失败
添加 replaceData 按钮
replaceData.setOnClickListener{ val db = dbHelper.writableDatabase db.beginTransaction() // 开启事务 try { db.delete("Book", null, null) if (true) { // 手动抛出,让事务失败 throw NullPointerException() } val values = ContentValues().apply { put("name", "Game of Thrones") put("author", "George Martin") put("pages", 720) put("price", 20.85) } db.insert("Book", null, values) db.setTransactionSuccessful() // 事务已经执行成功 } catch (e: Exception) { e.printStackTrace() } finally { db.endTransaction() } }
beginTransaction()方法开启一个事务
当所有的操作都完成之后,调用setTransactionSuccessful()表示事务已经执行成
功了
最后在finally代码块中调用endTransaction()结束事务
中途出现异常会导致事务的失败,此时旧数据应该是删除不掉的
每当升级一个数据库版本的时候,onUpgrade()方法里都一定要写一个相应的if判断语句。 保证跨版本升级数据库修改能被全部执行
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。