上篇有篇文章讲了数据库的操作 条件是:数据库已经建好的了,我们只需要从里面获取数据(查询)就可以了,
现在我们来看看第二种数据库的操作:
class SQLiteHelper extends SQLiteOpenHelper
封装一个继承SQLiteOpenHelper类的数据库操作类。SQLiteOpenHelper类是一个抽象的辅助类,主要用来生成一个数据库并对数据库的版本进行管理,在SQLiteOpenHelper类的构造方法中分别传入Context、数据库名称,CursorFactory(一般传入null,否则为默认数据库),数据库版本号(不能为负数)。
在SQLiteOpenHelper中首先执行的是onCreate方法(当数据库第一次创建时),一般在这个方法里生成数据表。
要注意的是,在构造函数时并没有真正创建数据库,而是在调用getWriteableDatabase()或者getReadableDatabase()方法的时候系统才会真正创建数据库,
如果当时系统中不存在这个数据库,系统会自动生成一个数据库,然后返回SQLiteDatabase对象。
在继承这个类的时候,要实现里面的3个方法,其中前两个方法是必须重写的。
/** * 创建表 */ @Override public void onCreate(SQLiteDatabase db) { // TODO Auto-generated method stub db.execSQL("CREATE TABLE IF NOT EXISTS " TB_NAME "(" CityBean.ID " integer primary key," CityBean.CITY " varchar," CityBean.CODE " integer" ")"); } /** * 当检测与前一次创建数据库版本不一样时,先删除表再创建新表 */ @Override public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) { // TODO Auto-generated method stub db.execSQL("DROP TABLE IF EXISTS " TB_NAME);// 先删除表 onCreate(db);//再创建表 } 还有个onOpen(SQLiteDatabase db) 这个函数是:打开数据库时的回调函数,一般不会用到
该类的源代码如下:
代码语言:javascript复制import android.content.Context;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteDatabase.CursorFactory;
import android.database.sqlite.SQLiteOpenHelper;
public class SQLiteHelper extends SQLiteOpenHelper {
public static final String TB_NAME = "citys";
public SQLiteHelper(Context context, String name, CursorFactory factory,
int version) {
// version 就是 数据库的版本号
super(context, name, factory, version);
// TODO Auto-generated constructor stub
}
/**
* 创建表
*/
@Override
public void onCreate(SQLiteDatabase db) {
// TODO Auto-generated method stub
db.execSQL("CREATE TABLE IF NOT EXISTS "
TB_NAME "("
CityBean.ID " integer primary key,"
CityBean.CITY " varchar,"
CityBean.CODE " integer"
")");
}
/**
* 当检测与前一次创建数据库版本不一样时,先删除表再创建新表
*/
@Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
// TODO Auto-generated method stub
db.execSQL("DROP TABLE IF EXISTS " TB_NAME);// 先删除表
onCreate(db);//再创建表
}
/**
* 变更列名
* @param db
* @param oldColumn
* @param newColumn
* @param typeColumn
*/
public void updateColumn(SQLiteDatabase db, String oldColumn, String newColumn, String typeColumn){
try{
db.execSQL("ALTER TABLE "
TB_NAME " CHANGE "
oldColumn " " newColumn
" " typeColumn
);
}catch(Exception e){
e.printStackTrace();
}
}
}
使用这个类:
当我们在一个activity类中使用这个数据库的时候 步奏如下:
1.必须先定义一个类的成员变量 申明数据库名字 声明数据库的版本号 声明一个查询结果游标 申明一个数据库对象
private static String DB_NAME = "mycity.db";//数据库名字 private static int DB_VERSION = 1;//数据库版本号 private Cursor cursor;//查询结果游标集 private SQLiteDatabase db;//打开数据库返回对象 private SQLiteHelper dbHelper;//数据库操作类
2.在一个activity的onCreate(Bundle)里面初始化和使用上面的变量
try{ /* 初始化并创建数据库 */ dbHelper = new SQLiteHelper(this, DB_NAME, null, DB_VERSION); /* 创建表 */ db = dbHelper.getWritableDatabase(); //调用SQLiteHelper.OnCreate() /* 查询表,得到cursor对象 */ cursor = db.query(SQLiteHelper.TB_NAME, null, null, null, null, null, CityBean.CODE " DESC"); cursor.moveToFirst(); while(!cursor.isAfterLast() && (cursor.getString(1) != null)){ CityBean city = new CityBean(); city.setId(cursor.getString(0)); city.setCity(cursor.getString(1)); city.setCode(cursor.getString(2)); cityList.add(city); cursor.moveToNext(); } }catch(IllegalArgumentException e){ //当用SimpleCursorAdapter装载数据时,表ID列必须是_id,否则报错column '_id' does not exist e.printStackTrace(); //当版本变更时会调用SQLiteHelper.onUpgrade()方法重建表 注:表以前数据将丢失 DB_VERSION; dbHelper.onUpgrade(db, --DB_VERSION, DB_VERSION); }
3.在函数中使用:
查询:
cursor = db.query(true, SQLiteHelper.TB_NAME, new String[]{CityBean.ID, CityBean.CITY, CityBean.CODE}, sql, null, null, null, null, null);
添加:
Long cityID = db.insert(SQLiteHelper.TB_NAME, CityBean.ID, values); 插入成功的话会返回一个值
修改:
db.update(SQLiteHelper.TB_NAME, values, CityBean.ID "=" cityList.get(POSTION).getId(), null);
删除:
db.delete(SQLiteHelper.TB_NAME, CityBean.ID "=" view.getId(), null);
4.在activity销毁之后需要关闭数据库的:
在activity的生命周期函数onDestroy()里面加上下面的代码
@Override protected void onDestroy() { db.delete(SQLiteHelper.TB_NAME, null, null); super.onDestroy(); }
至此 一个简单的数据库操作基本完成了,下面我们来看看需要掌握的知识:
Android中每一个数据库对创建它的应用程序包套件来说都是私有的,默认情况下其他应用程序无法直接访问此私有数据库。所有的数据库文件存放在手机中的/data/data/package_name/databases路径下,以下是常用的与数据库相关的函数:
那么我们首先需要学习一下数据库的 创建函数 打开函数 关闭函数
返回值 | 函数 | 备注 |
---|---|---|
static SQLiteDatabase | create(SQLiteDatabase.CursorFactory factory) | 创建一个数据库 factory:可选的数据库游标工厂类,当查询(query)被提交时,该对象会被调用来实例化一个游标。 |
static SQLiteDatabase | openDatabase(String path,SQLiteDatabase.CursorFactory factory,int flags) | 根据提供的模式打开一个数据库 path:打开或创建的数据库文件 factory:可选的数据库游标工厂类,当查询(query)被提交时,该对象会被调用来实例化一个游标。默认为null。 flags:控制数据库的访问模式。主要有以下几种模式: l OPEN_READWRITE l OPEN_READONLY l CREATE_IF_NECESSARY l NO_LOCALIZED_COLLATORS |
static SQLiteDatabase | openOrCreateDatabase(File file, SQLiteDatabase.CursorFactory factory) | 等同于openDatabase(file.getPath(), factory, CREATE_IF_NECESSARY) |
static SQLiteDatabase | openOrCreateDatabase(String path, SQLiteDatabase.CursorFactory factory) | 等同于openDatabase(path,factory, CREATE_IF_NECESSARY) |
void | close() | 关闭数据库 |
boolean | deleteDatabase(String name) | 删除指定的数据库 name:要关闭的数据库的名字 |
上面表格里面的有些参数请看我的上面一篇文章 地址: http://blog.csdn.net/u014737138/article/details/40618003
这些函数的使用方法:
代码语言:javascript复制//创建数据库
SQLiteDatabase mydataBase=SQLiteDatabase.create(new CursorFactory(){
//工厂类,一个可选工厂类,当查询时调用来实例化一个游标
@Override
public Cursor newCursor(SQLiteDatabase db,
SQLiteCursorDriver masterQuery, String editTable,
SQLiteQuery query) {
// TODO Auto-generated method stub
return null;
}
});
//创建或打开数据库
SQLiteDatabase myDataBase=this.openOrCreateDatabase("myDataBase.db",
MODE_PRIVATE, new CursorFactory(){
//创建新的数据库,名称myDatabase,模式MODE_PRIVATE,可选的游标工厂类
@Override
public Cursor newCursor(SQLiteDatabase db,
SQLiteCursorDriver masterQuery, String editTable,
SQLiteQuery query) {
// TODO Auto-generated method stub
return null;
}
});
SQLiteDatabase myDataBase=this.openOrCreateDatabase("myDataBase.db",MODE_PRIVATE,null);
//关闭数据库
myDataBase.close();
//删除指定名称的数据库
this.deleteDatabase(“myDatabase.db”);
2.对数据库表的操作 主要是建表:这个是一个非查询操作 一般使用execSQL(sql)命令来执行
在对数据库中的表进行相关操作时,可以使用非查询的execSQL(String sql)来执行。示例代码如下:
String CREATE_TABLE = “create table table1 (_id integer primary key autoincrement,number integer,data text)”; //创建表
myDataBase.execSQL(CREATE_TABLE); 1)对表的插入操作:
long insert(String table, String nullColumnHack, ContentValues values) 向表中插入一条数据 参数: table:想要插入数据的表名 nullColumnHack:SQL不允许插入空行,初始化值为空时,这一列将会被显示地赋一个null值 values:要插入的值,类型为ContentValues
ContentValues主要是存放表中的数据段,以及其对应的值,与map一样采用名值对的形式存储,但是它存储的名值对中,名是一个String类型,值是基本数据类型。其使用示例如下:简单的理解他就是键值对,跟map一样,如果你看源代码,它其实就是继承他们并实现的。
ContentValues args = new ContentValues(); args.put(KEY_TITLE, title); args.put(KEY_BODY, body); myDataBase.update(DATABASE_TABLE, args, KEY_ROWID "=" rowId, null); |
---|
2)对表的更新 修改操作
int update(String table, ContentValues values, String whereClause, String[] whereArgs) 修改表中的数据 table:想要修改数据的表名 values:要更新的值,使用方法看上面的例子 whereClause:可选的where子句,如果其值为null,将会修改所有的行。 whereArgs:当在whereClause中包含”?”时,如果whereArgs的值不为null,则这个数组中的值将依次替换whereClause中出现的”?” ?就是写sql语句占位符
3)删除一行数据
int delete(String table, String whereClause, String[] whereArgs) 从表中删除一行数据 table:想要删除数据的表名 whereClause:可选的where子句,如果其值为null,将会删除所有的行。 whereArgs:当在whereClause中包含”?”时,如果whereArgs的值不为null,则这个数组中的值将依次替换whereClause中出现的”?”
4)查询表操作
Cursor query(String table, String[] columns, String selection, String[] selectionArgs, String groupBy, String having, String orderBy, String limit) 查询数据表 table:要查询数据的表名 columns:要返回的列的列名数组 selection:可选的where子句 ,如果其值为null,将会返回所有的行 selectionArgs:当在selection中包含”?”时,如果selectionArgs的值不为null,则这个数组中的值将依次替换selection中出现的”?” groupBy:可选的group by子句,如果其值为null,将不会对行进行分组 having:可选的having子句,如果其值为null,将会包含所有的分组 orderBy:可选的order by子句,如果其值为null,将会使用默认的排序规则 limit:可选的limit子句,如果其值为null,将不会包含limit子句
3.关于游标Cursor学习:
Android采用游标对从数据库中查询出来的结果进行随机的读写访问,在查询数据库后,将结果返回给游标(即android.database.Cursor),这是查询结果的记录集,示意图如下:
_id | someNumber | |
---|---|---|
1 | 8 | |
2 | 10 | |
3 | 2 |
Cursor类常见的方法如下:
返回值 | 函数 | 备注 |
---|---|---|
boolean | move(int offset) | 以当前位置为参考,将Cursor移动指定数目的位置(相对位置) |
boolean | moveToPosition(int position) | 将Cursor移动到指定位置(绝对位置) |
boolean | moveToNext() | 将Cursor向前移动一个位置 |
boolean | moveToLast() | 将Cursor向后移动一个位置 |
boolean | moveToFirst() | 将Cursor移动到第一行 |
boolean | isBeforeFirst() | 返回Cursor是否指向第一项数据之前 |
boolean | isAfterLast() | 返回Cursor是否指向最后一项数据之后 |
boolean | isClosed() | 返回Cursor是否关闭 |
boolean | isFirst() | 返回Cursor是否指向第一项数据 |
boolean | isLast() | 返回Cursor是否指向最后一项数据 |
boolean | isNull(int columnIndex) | 返回指定位置的值是否为null |
int | getCount() | 返回总的项目总数 |
int | getInt(int columnIndex) | 返回指定列中的数据的int型表示 |
int | getColumnIndex(String columnName) | 按给定的列的名字返回列的索引值,如果不存在则返回 -1 |
特别提示:
要创建一个Cursor(游标),必须执行一个查询,通过SQL使用rawQuery()方法或是更精心的query()方法,而不能使用execSQL(String sql)【戴帽子】方法。以下为Cursor的使用示例:
Cursor cur=myDataBase.rawQuery("select * from test", null);
if(cur!=null){//游标不为空
//返回给定名称的列的基于0开始的index,如果该属性列不存在则返回-1
//通过它们的index来检索属性值
int numColumn=cur.getColumnIndex("someNumber");
if(cur.moveToFirst()){ //cur.moveToFirst()让游标指向第一行,如果游标指向第一行,则返回true
do {
int num=cur.getInt(numColumn);//获得当前行该属性的值
/*Cursor提供了不同的方法来回索不同的数据类型,例如getInt(int index)/getString(int index)等等*/
/*做一些事情*/
} while (cur.moveToNext());
/*游标移动到下一行,如果游标已经到达结果集中的最后,即没有行可以移动时,则返回false*/
//其他可能移动的是 moveToPrevious() 和moveToFirst()方法
}
}
至此数据库的函数基本学习了一篇,现在就是以后如何去熟练的使用它们了
最后还是总结下 public class SQLiteHelper extends SQLiteOpenHelper{}做法经常用到的两个函数:
返回值 | 函数 | 备注 |
---|---|---|
public void | onCreate(SQLiteDatabase db) | 在数据库第一次生成时会调用这个方法,一般我们在这个方法里生成数据表 |
public void | onUpgrade(SQLiteDatabase db,int oldVersion,int newVersion) | 当数据库需要升级时,系统会自动调用这个方法,一般我们在这个方法里删除数据表,并建立新的数据表,并根据实际需求做其他的操作 |
public void | onOpen(SQLiteDatabase db) | 这是打开数据库时的回调函数,一般不会用到 |