当前位置:首页 » Android开发技术

Android SQLite数据库操作示例

2014-07-01 18:48 本站整理 浏览(8)

SQLite and Android

SQLite简介

SQLite是一个非常流行的嵌入式数据库,它支持SQL语言,并且只利用很少的内存就有很好的性能。此外,它还是开源的,任何人都可以使用它。
SQLite由以下几个组件组成:SQL编译器、内核、后端以及附件。SQLite通过利用虚拟机和虚拟数据库引擎(VDBE),使调试、修改和扩展SQLite的内核变得更加方便。
SQLite支持的数据类型包括:
TEXT (类似于Java的String)
INTEGER (类似于Java的long)
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().

参考链接

[1]http://www.ibm.com/developerworks/cn/opensource/os-cn-sqlite/