我们在编写数据库应用软件时,需要考虑这样的问题:因为我们开发的软件可能会安装在很多用户的手机上,如果应用使用到了SQLite数据库,我们必须在用户初次使用软件时创建出应用使用到的数据库表结构及添加一些初始化记录,另外在软件升级的时候,也需要对数据表结构进行更新。那么,我们如何才能实现在用户初次使用或升级软件时自动在用户的手机上创建出应用需要的数据库表呢?总不能让我们在每个需要安装此软件的手机上通过手工方式创建数据库表吧?因为这种需求是每个数据库应用都要面临的,所以在Android系统,为我们提供了一个名为SQLiteOpenHelper的抽象类,必须继承它才能使用,它是通过对数据库版本进行管理来实现前面提出的需求。
下面我们来看一下Android SQLite 最常用的几个类和那些方法:
一、SQLiteOpenHelper :
onCreate(SQLiteDatabase db);
用于初次使用软件时生成数据库表。
当调用SQLiteOpenHelper的getWritableDatabase()或者getReadableDatabase()方法获取用于操作数据库的SQLiteDatabase实例的时候,
如果数据库不存在,Android系统会自动生成一个数据库,接着调用onCreate()方法,onCreate()方法在初次生成数据库时才会被调用,
在onCreate()方法里可以生成数据库表结构及添加一些应用使用到的初始化数据
onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion);
在数据库的版本发生变化时会被调用,一般在软件升级时才需改变版本号
getWritableDatabase();
getReadableDatabase();
两方法都可以获取一个用于操作数据库的SQLiteDatabase实例。但getWritableDatabase() 方法以读写方式打开数据库,一旦数据库的磁盘空间满了,数据库就只能读而不能写,倘若使用getWritableDatabase()打开数据库就会出错。getReadableDatabase()方法先以读写方式打开数据库,如果数据库的磁盘空间满了,就会打开失败,当打开失败后会继续尝试以只读方式打开数据库。
二、SQLiteDatabase:
1、db.insert(table, nullColumnHack, values)
第一个参数是表名称,第二个参数是空列的默认值,第三个参数是ContentValues类型的一个封装了列名称和列值的Map;
2、db.delete(table, whereClause, whereArgs)
第一个参数是表名称,第二个参数是删除条件,第三个参数是删除条件值数组
3、db.update(table, values, whereClause, whereArgs)
第一个参数是表名称,第二个参数是更行列ContentValues类型的键值对(Map),第三个参数是更新条件(where字句),第四个参数是更新条件数组
4、db.query(table, columns, selection, selectionArgs, groupBy, having, orderBy)(下面有对该方法详细讲解)
5、db.execSQL(sql) // 执行任何SQL语句
6、db.rawQuery(sql, selectionArgs)
对第四个方法详细讲解:
Cursor query(table, columns, selection, selectionArgs, groupBy, having, orderBy, limit)
各个参数的意义说明:
①table:表名称
②columns:列名称数组
③selection:条件字句,相当于where
④selectionArgs:条件字句,参数数组
⑤groupBy:分组列
⑥having:分组条件
⑦orderBy:排序列
⑧limit:分页查询限制
三、Cursor:
Cursor是一个游标接口,提供了遍历查询结果的方法,如移动指针方法move(),获得列值方法getString()等.
Cursor游标常用方法:
getCount() 总记录条数
isFirst() 判断是否第一条记录
isLast() 判断是否最后一条记录
moveToFirst() 移动到第一条记录
moveToLast() 移动到最后一条记录
move(int offset) 移动到指定记录
moveToNext() 移动到下一条记录
moveToPrevious() 移动到上一条记录
getColumnIndexOrThrow(String columnName) 根据列名称获得列索引
getInt(int columnIndex) 获得指定列索引的int类型值
getString(int columnIndex) 获得指定列缩影的String类型值
四、综合例子:
public class DBHelper { public static final String DB_ACTION="db_action";//LogCat private static final String DB_NAME="people.db";//数据库名 private static final String DB_TABLE="peopleinfo";//数据库表名 private static final int DB_VERSION=1;//数据库版本号 public static final String KEY_ID = "_id"; //表属性ID public static final String KEY_NAME = "name";//表属性name public static final String KEY_AGE = "age";//表属性age public static final String KEY_HEIGHT = "height";//表属性height private SQLiteDatabase db ; private Context xContext ; private DBOpenHelper dbOpenHelper ; public DBHelper(Context context) { xContext = context ; } /** 空间不够存储的时候设为只读 * @throws SQLiteException */ public void open() throws SQLiteException { dbOpenHelper = new DBOpenHelper(xContext, DB_NAME, null,DB_VERSION); try { db = dbOpenHelper.getWritableDatabase(); } catch (SQLiteException e) { db = dbOpenHelper.getReadableDatabase(); } } public void close() { if(db != null) { db.close(); db = null; } } /** * 向表中添加一条数据 * @param people * @return */ public long insert(People people) { ContentValues newValues = new ContentValues(); newValues.put(KEY_NAME, people.Name); newValues.put(KEY_AGE, people.Age); newValues.put(KEY_HEIGHT, people.Height); return db.insert(DB_TABLE, null, newValues); } /** * 删除一条数据 * @param id * @return */ public long deleteOneData(long id) { return db.delete(DB_TABLE, KEY_ID+"="+id, null ); } /** * 删除所有数据 * @return */ public long deleteAllData() { return db.delete(DB_TABLE, null, null); } /** * 根据id查询数据的代码 * @param id * @return */ public People[] queryOneData(long id) { Cursor result = db.query(DB_TABLE, new String[] {KEY_ID,KEY_NAME,KEY_AGE,KEY_HEIGHT}, KEY_ID+"="+id, null, null, null, null); return ConvertToPeople(result) ; } /** * 查询全部数据的代码 * @return */ public People[] queryAllData() { Cursor result = db.query(DB_TABLE, new String[] {KEY_ID,KEY_NAME,KEY_AGE,KEY_HEIGHT}, null, null, null, null, null); return ConvertToPeople(result); } public long updateOneData(long id ,People people) { ContentValues newValues = new ContentValues(); newValues.put(KEY_NAME, people.Name); newValues.put(KEY_AGE, people.Age); newValues.put(KEY_HEIGHT, people.Height); return db.update(DB_TABLE, newValues, KEY_ID+"="+id, null); } private People[] ConvertToPeople(Cursor cursor) { int resultCounts = cursor.getCount(); if(resultCounts == 0 || !cursor.moveToFirst()) { return null ; } People[] peoples = new People[resultCounts]; Log.i(DB_ACTION, "PeoPle len:"+peoples.length); for (int i = 0; i < resultCounts; i++) { peoples[i] = new People(); peoples[i].ID = cursor.getInt(0); peoples[i].Name = cursor.getString(cursor.getColumnIndex(KEY_NAME)); peoples[i].Age = cursor.getInt(cursor.getColumnIndex(KEY_AGE)); peoples[i].Height = cursor.getFloat(cursor.getColumnIndex(KEY_HEIGHT)); Log.i(DB_ACTION, "people "+i+"info :"+peoples[i].toString()); cursor.moveToNext(); } return peoples; } /** * 静态Helper类,用于建立、更新和打开数据库 */ private static class DBOpenHelper extends SQLiteOpenHelper { /* * 手动建库代码 CREATE TABLE peopleinfo (_id integer primary key autoincrement, name text not null, age integer, height float);*/ private static final String DB_CREATE= "CREATE TABLE "+DB_TABLE +" ("+KEY_ID+" integer primary key autoincrement, " +KEY_NAME+" text not null, " +KEY_AGE+" integer,"+ KEY_HEIGHT+" float);"; public DBOpenHelper(Context context, String name, CursorFactory factory, int version) { super(context, name, factory, version); } @Override public void onCreate(SQLiteDatabase db) { db.execSQL(DB_CREATE); Log.i(DB_ACTION, "onCreate"); } @Override public void onUpgrade(SQLiteDatabase _db, int oldVersion, int newVersion) { //函数在数据库需要升级时被调用, //一般用来删除旧的数据库表, //并将数据转移到新版本的数据库表中 _db.execSQL("DROP TABLE IF EXISTS "+DB_TABLE); onCreate(_db); Log.i(DB_ACTION, "Upgrade"); } } }
五、小技巧
在Android中通过导入静态数据库来提高应用第一次的启动速度
http://www.cnblogs.com/west-link/archive/2012/02/20/2358719.html
http://antkingwei.iteye.com/blog/1448154