Android编程之SQLite数据库操作方法详解
本文实例讲述了Android SQLite数据库操作方法。分享给大家供大家参考,具体如下:
SQLite and Android
SQLite简介
SQLite是一个非常流行的嵌入式数据库,它支持SQL语言,并且只利用很少的内存就有很好的性能。此外,它还是开源的,任何人都可以使用它。
SQLite由以下几个组件组成:SQL编译器、内核、后端以及附件。SQLite通过利用虚拟机和虚拟数据库引擎(VDBE),使调试、修改和扩展SQLite的内核变得更加方便。
SQLite支持的数据类型包括:
1. TEXT (类似于Java的String) 2. INTEGER (类似于Java的long) 3. REAL (类似于Java的Double)
更多SQLite数据类型知识可以参考前面相关文章入:详解SQLite中的数据类型
SQLite In Android
Android在运行时集成了SQLite,因此在Android中使用SQLite数据库并不需要安装过程和获取数据库使用权限,你只需要定义创建和更新数据库的语句即可,其他的会由Android平台替你搞定。
操作SQLite数据库通常意味着操作文件系统,这种操作还是比较耗时的,因此建议将数据库操作异步执行。
你的应用创建一个SQLite数据库,数据在默认情况下,存储在/DATA/data/APP_NAME/databases/FILENAME。这里DATA是Environment.getDataDirectory()方法返回的值,APP_NAME是你的应用包名
Android开发中使用SQLite数据库
Activity可以使用Content Provider或者 Service访问一个数据库。
创建数据库
Android不自动提供数据库。在Android应用程序中使用SQLite,必须自己创建数据库,然后创建表、索引、填充数据。Android提供了一个SQLiteOpenHelper帮助你创建一个数据库,你只要继承 SQLiteOpenHelper 类,就可以轻松的创建数据库。
SQLiteOpenHelper 类根据开发应用程序的需要,封装了创建和更新数据库使用的逻辑。SQLiteOpenHelper 的子类,至少需要实现三个方法:
构造函数,调用父类SQLiteOpenHelper的构造函数。这个方法需要四个参数:上下文环境,数据库名字,一个可选的游标工厂(通常是NULL),一个代表你正在使用的数据库模型版本的整数。 onCreate()方法,它需要一个SQLiteDatabase对象作为参数,根据需要对这个对象填充表和初始化数据。 onUpgrade()方法,它需要三个参数,一个SQLiteDatabase对象,一个旧的版本号和一个新的版本号,这样你就可以清楚如何把一个数据库从旧的模型转变为新的模型。
首先,定义需要创建的表结构,使用类来进行抽象,这里示例定义一个新浪微薄的帐号类:
public class AccountTable {
public static final String TABLE_NAME = "account_table";
public static final String UID = "uid";
public static final String USERNAME = "username";
public static final String USERNICK = "usernick";
public static final String AVATAR_URL = "avatar_url";
public static final String PORTRAIT = "portrait";
public static final String OAUTH_TOKEN = "oauth_token";
public static final String OAUTH_TOKEN_SECRET = "oauth_token_secret";
public static final String INFOJSON = "json";
}
下面代码展示了如何继承SQLiteOpenHelper创建数据库,推荐使用单例类:
import android.content.Context;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteOpenHelper;
import org.qii.weiciyuan.support.database.table.*;
class DatabaseHelper extends SQLiteOpenHelper {
private static DatabaseHelper singleton = null;
private static final String DATABASE_NAME = "weibo.db";
private static final int DATABASE_VERSION = 16;
static final String CREATE_ACCOUNT_TABLE_SQL = "create table " + AccountTable.TABLE_NAME
+ "("
+ AccountTable.UID + " integer primary key autoincrement,"
+ AccountTable.OAUTH_TOKEN + " text,"
+ AccountTable.OAUTH_TOKEN_SECRET + " text,"
+ AccountTable.PORTRAIT + " text,"
+ AccountTable.USERNAME + " text,"
+ AccountTable.USERNICK + " text,"
+ AccountTable.AVATAR_URL + " text,"
+ AccountTable.INFOJSON + " text"
+ ");";
DatabaseHelper(Context context) {
super(context, DATABASE_NAME, null, DATABASE_VERSION);
}
@Override
public void onCreate(SQLiteDatabase db) {
db.execSQL(CREATE_ACCOUNT_TABLE_SQL);
}
@Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
switch (oldVersion) {
default:
deleteAllTable(db);
onCreate(db);
}
}
public static synchronized DatabaseHelper getInstance() {
if (singleton == null) {
singleton = new DatabaseHelper(GlobalContext.getInstance());
}
return singleton;
}
private void deleteAllTable(SQLiteDatabase db) {
db.execSQL("DROP TABLE IF EXISTS " + AccountTable.TABLE_NAME);
}
}
增删改查数据库
因为SQLite支持标准的SQL语句,因此我们可以用标准SQL语句才增删改查数据库,推荐使用占位符的sql语句,看起来更加清爽,下面是我的代码示例:
package com.hw.droid.hwcatalog;
public class DatabaseManager {
private static DatabaseManager singleton = null;
private SQLiteDatabase wsd = null;
private SQLiteDatabase rsd = null;
private DatabaseManager() {
}
public static DatabaseManager getInstance(Context context) {
if (singleton == null) {
synchronized (DatabaseManager.class) {
if (singleton == null) {
DatabaseHelper databaseHelper = DatabaseHelper.getInstance(context);
singleton = new DatabaseManager();
singleton.wsd = databaseHelper.getWritableDatabase();
singleton.rsd = databaseHelper.getReadableDatabase();
}
}
}
return singleton;
}
public void initAccountTable(List<AccountData listDatas) {
if (listDatas == null || listDatas.size() <= 0) {
return;
}
wsd.beginTransaction();
try {
for (AccountData data : listDatas) {
insertAccountTable(data);
}
wsd.setTransactionSuccessful();
} finally {
wsd.endTransaction();
}
}
private void insertAccountTable(AccountData accData) {
String sql = "insert into " + AccountTable.TABLE_NAME + "(" + AccountTable.USERNAME + ", "
+ AccountTable.USERNICK + ", " + AccountTable.AVATAR_URL + ", " + AccountTable.PORTRAIT + ", "
+ AccountTable.OAUTH_TOKEN + ", " + AccountTable.OAUTH_TOKEN_SECRET + ", " + AccountTable.INFOJSON
+ " " + ")" + " values(?, ?, ?, ?, ?, ?, ?)";
wsd.execSQL(sql,
new Object[] { accData.getUserName(), accData.getUserNick(), accData.getUrl(), accData.getPort(),
accData.getToken(), accData.getSecret(), accData.getJson(), accData.getThreads(), });
}
public List<AccountData getAccountDatas() {
List<AccountData listDatas = selectAccountData();
return listDatas;
}
private List<AccountData selectAccountData() {
List<AccountData listAccountData = new ArrayList<AccountData ();
String querySql = "select " + AccountTable.USERNAME + ", " + AccountTable.USERNICK + ", " + AccountTable.AVATAR_URL + ", " + AccountTable.PORTRAIT + ", " + AccountTable.OAUTH_TOKEN + ", " + AccountTable.OAUTH_TOKEN_SECRET + ", " + AccountTable.INFOJSON " " + " from " + BbsForumsTable.TABLE_NAME;
Cursor cursor = rsd.rawQuery(querySql, null);
if (cursor.moveToFirst()) {
do {
AccountData data = new AccountData();
data.setUserName(cursor.getString(cursor.getColumnIndex(AccountTable.USERNAME)));
data.setUserNick(cursor.getString(cursor.getColumnIndex(AccountTable.USERNICK)));
data.setUrl(cursor.getString(cursor.getColumnIndex(AccountTable.AVATAR_URL)));
data.setPort(cursor.getString(cursor.getColumnIndex(AccountTable.PORTRAIT)));
data.setToken(cursor.getString(cursor.getColumnIndex(AccountTable.OAUTH_TOKEN)));
data.setSecret(cursor.getString(cursor.getColumnIndex(AccountTable.OAUTH_TOKEN_SECRET)));
data.setJson(cursor.getString(cursor.getColumnIndex(AccountTable.INFOJSON)));
listAccountData.add(data);
} while (cursor.moveToNext());
}
cursor.close();
return listAccountData;
}
public void deleteBbsDatas() {
String delSql = "delete from " + AccountTable.TABLE_NAME;
wsd.execSQL(delSql);
}
}
事物(DBTransaction)
Android中经常会用到数据库缓存,特别是wifi情况下遇到数据不一致情况需要更新缓存数据,这个时候就需要用到事物处理,保证操作的完整性和速度。Android中使用SQLite保证事务完整性示例如下:
public void initAccountTable(List<AccountData listDatas) {
if (listDatas == null || listDatas.size() <= 0) {
return;
}
wsd.beginTransaction();
try {
for (AccountData data : listDatas) {
insertAccountTable(data);
}
wsd.setTransactionSuccessful();
} finally {
wsd.endTransaction();
}
}
通过beginTransaction()开启事务,endTransaction()结束事务,并且设置事务执行成功标识setTransactionSuccessful().
希望本文所述对大家Android程序设计有所帮助。
- 【自然框架】QuickPager分页控件的总体介绍和在线演示
- 在C++中反射调用.NET(三) 使用非泛型集合的委托方法C++中的列表对象list C++传递集合数据给.NET创建泛型List实例反射静态方法反射调用索引器当委托遇到协变和逆变C++/CLI
- 如何使用树莓派自制网络监视器
- 利用雅虎小型企业服务平台的目录遍历漏洞查看客户的信用卡信息
- 【自然框架】QuickPager asp.net 分页控件的Ajax分页方式。
- 骑行在华盛顿 针对320万次共享单车骑行数据的分析
- 【自然框架】QuickPagerSQL——专门生成分页用的SQL的类库
- 【数据科学】数据科学中的 Spark 入门
- 【自然框架】QuickPager分页控件的单独的源码 V2.0.4.2。
- 用 iPhoneX 的 FaceID 刷脸解锁真的靠谱吗?
- 【自然框架】用CMS的栏目举例,聊一聊从“一层”到“三层”的变化
- java如何自定义鼠标指针
- 面向对象最重要的是“抽象”,三层最重要的也是“抽象”,没有抽象就不是真正的面向对象、三层。
- 唯一不变的就是一直在变”--“数据”的华丽“变身术”
- java教程
- Java快速入门
- Java 开发环境配置
- Java基本语法
- Java 对象和类
- Java 基本数据类型
- Java 变量类型
- Java 修饰符
- Java 运算符
- Java 循环结构
- Java 分支结构
- Java Number类
- Java Character类
- Java String类
- Java StringBuffer和StringBuilder类
- Java 数组
- Java 日期时间
- Java 正则表达式
- Java 方法
- Java 流(Stream)、文件(File)和IO
- Java 异常处理
- Java 继承
- Java 重写(Override)与重载(Overload)
- Java 多态
- Java 抽象类
- Java 封装
- Java 接口
- Java 包(package)
- Java 数据结构
- Java 集合框架
- Java 泛型
- Java 序列化
- Java 网络编程
- Java 发送邮件
- Java 多线程编程
- Java Applet基础
- Java 文档注释
- 二叉树:层序遍历登场!
- 二叉树:前中后序迭代方式的写法就不能统一一下么?
- 二叉树:听说递归能做的,栈也能做!
- 二叉树:一入递归深似海,从此offer是路人
- 关于二叉树,你该了解这些!
- 双指针法:总结篇!
- 栈与队列:总结篇!
- Appium移动端自动化测试--元素操作与触摸动作【移动端自动化测试教程奉上】
- 接口测试Mock利器--moco runner是如何工作的?
- Java中类型判断的几种方式
- 如何实现类似@Component的Spring动态注入功能
- 一次代码优化实践,用了模板方法+策略+工厂方法模式
- 给 JDK 报了一个 P4 的 Bug,结果居然……
- Git | Git Server 搭建
- leetcode树之二叉树的深度