核心:SQLiteOpenHelper帮助类(是一个抽象类)
借助这个类就可以非常简单地对数据库进行创建和升级;
创建数据库
SQLiteOpenHelper是抽象类,需创建自己的类继承;
其中有两个抽象方法,
onCreate()
和onUpgrade()
,
需重写,实现创建
和升级
数据库的逻辑。还有两个重要的实例方法:
getReadableDatabase()
和getWritableDatabase()
。
都可创建
或打开现有数据库
(数据库已经存在则直接打开,没有则创建),
并返回可对数据库进行读写操作的对象。
其不同:当数据库不可写入时(如磁盘空间已满)
,
前者
返回的对象以getReadableDatabase()
打开数据库,getWritableDatabase()
将出现异常
。SQLiteOpenHelper
有两个构造方法可供重写,
一般使用参数少一点的那个构造方法,
其接收四个参数:
Context
,
数据库名
,创建数据库时使用的就是这里指定的名称
;
允许
查询数据时返回一个自定义的Cursor(一般传入null),
当前数据库版本号
(用于升级
操作)。
构建SQLiteOpenHelper实例
后,
再调用他的getReadableDatabase()/getWritableDatabase()方法
就能创建数据库
了
(数据库文件会存放在/data/data/
目录下)。
此时重写的onCreate()方法
被执行(通常处理创建表的逻辑
)。!!!!!!
示例代码
创建名为BookStore.db
的数据库,并新建一张Book
表。
新建MyDatabaseHelper
类继承自SQLiteOpenHelper
:
public class MyDatabaseHelper extends SQLiteOpenHelper {
//将见表语句定义成字符串常量
public static final String CREATE_BOOK = "create table Book ("
+ "id integer primary key autoincrement, "
+ "author text, "
+ "price real, "
+ "pages integer, "
+ "name text)" ;
private Context mContext;
public MyDatabaseHelper(Context context, String name, SQLiteDatabase.CursorFactory factory, int version) {
super(context, name, factory, version);
mContext = context;
}
@Override
public void onCreate(SQLiteDatabase db) {
//在数据库创建完成时创建Book表
db.execSQL(CREATE_BOOK);
Toast.makeText(mContext, "Create succeeded", Toast.LENGTH_SHORT).show();
}
@Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
}
}
注意
autoincrement
表示id
是自增长的;
使用MyDatabaseHelper
创建数据库
public class MainActivity extends AppCompatActivity {
private MyDatabaseHelper dbhelper;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
//构建SQLiteOpenHelper实例
dbhelper = new MyDatabaseHelper(this, "BookStore.db", null, 1);
Button createDatabase = (Button) findViewById(R.id.create_database);
createDatabase.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
//调用SQLiteOpenHelper实例的getReadableDatabase()/getWritableDatabase()方法
//就能创建数据库了
//此时重写的onCreate()方法被执行
//如以上所写,则创建了Book表
dbhelper.getWritableDatabase();
}
});
}
}
升级(更新)数据库
基于以上代码,
再添加一张Category表用于记录图书分类,
在继承自SQLiteOpenHelper
的MyDatabaseHelper
类中添加代码:
(添加的地方以感叹号标记,一共四处)
public class MyDatabaseHelper extends SQLiteOpenHelper {
//将见表语句定义成字符串常量
public static final String CREATE_BOOK = "create table Book ("
+ "id integer primary key autoincrement, "
+ "author text, "
+ "price real, "
+ "pages integer, "
+ "name text)" ;
//!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! 1.
public static final String CREATE_CATEGORY = "create table Category ("
+ "id integer primary key autoincrement, "
+ "category_name text, "
+ "category_code integer)";**
private Context mContext;
public MyDatabaseHelper(Context context, String name, SQLiteDatabase.CursorFactory factory, int version) {
super(context, name, factory, version);
mContext = context;
}
@Override
public void onCreate(SQLiteDatabase db) {
//在数据库创建完成时创建Book表
db.execSQL(CREATE_BOOK);
//!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! 2.
db.execSQL(CREATE_CATEGORY);
Toast.makeText(mContext, "Create succeeded", Toast.LENGTH_SHORT).show();
}
@Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
//!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! 3.
db.execSQL("drop table if exists Book");
db.execSQL("drop table if exists Category");
onCreate(db); //!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! 4.
}
}
再次调用
getWritableDatabase();
时,
onCreate()
不会再执行了,
因为数据库只能创建一次,刚刚已经创建过了;
所以这里只能在onUpgrade()
中,
执行Drop
将原来的表删掉,
再重新调用onCreate()
方法,
这样一开始的表
和新加的表
都会被创建;
调用onUpgrade()
:
构造SQLiteOpenHelper
实例的时候,
给第四个参数(version)
传入大于旧版本的数字
,
即可让onUpgrade()
执行,进而更新数据库:
public class MainActivity extends AppCompatActivity {
private MyDatabaseHelper dbhelper;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
//!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
dbhelper = new MyDatabaseHelper(this, "BookStore.db", null, 2);
//!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
Button createDatabase = (Button) findViewById(R.id.create_database);
createDatabase.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
dbhelper.getWritableDatabase();
}
});
}
}
CRUD核心:
getReadableDatabase()
和getWritableDatabase()
返回的SQLiteDatabase
对象;
在Android中即使不去编写SQL语句,
提供了一系列辅助性方法,
也能轻松完成所有CRUD操作。
SQLiteOpenHelper的两个实例方法getReadableDatabase()/getWritableDatabase()
会返回SQLiteDatabase对象,
借助这个对象就可对数据进行CRUD操作。
添加数据
首先调用
ContentValues
实例的各种重载的put(表的某个属性,值)
方法,
向ContentValues
实例自身中添加数据;
接着调用insert()
,即可将数据加到对应的表中;
它接收三个参数:
- 表名,指定向哪张表添加数据;
- 用于在未指定添加数据的情况下,
给某些可为空的列自动复赋值NULL,
一般用不到这个功能,
直接传入NULL即可;ContentValues
实例;
public class MainActivity extends AppCompatActivity {
private MyDatabaseHelper dbhelper;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
dbhelper = new MyDatabaseHelper(this, "BookStore.db", null, 2);
Button createDatabase = ...
Button addData = (Button) findViewById(R.id.add_data);
addData.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
SQLiteDatabase db = dbhelper.getWritableDatabase();
ContentValues values = new ContentValues();
//开始组装第一条数据
values.put("name", "The Da Vinci Code");
values.put("author", "Dan Brown");
values.put("pages",454);
values.put("price", 16.96);
db.insert("Book",null,values);//插入第一条数据
values.clear();//!!!!!
//开始组装第二条数据
values.put("name", "The Lost Symbol");
values.put("author", "Dan Brown");
values.put("pages",510);
values.put("price", 19.95);
db.insert("Book",null,values);//插入第二条数据
}
});
...
更新数据
- 首先调用
ContentValues
实例的各种重载的put(表的某个属性,值)
方法,- 接着调用
update()
实现更新——
第三、四个参数用于约束更新
某一行或某几行数据,
默认更新所有行;
第三个参数对应SQL的where语句,?
为占位符
,
通过第四个参数提供的字符串数组
指定相应内容
;
第一参数表名,第二参数ContentValues
实例;
Button updateData = (Button) findViewById(R.id.update_data);
updateData.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
SQLiteDatabase db = dbhelper.getWritableDatabase();
ContentValues values = new ContentValues();
values.put("price", 10.99);
db.update("Book",values, "name = ?", new String[]{"The Da Vinci Code"});
}
});
上述代码表达的意图将name为The Da Vinci Code的这本书的价格改成10.99;
删除数据
- 直接用
SQLiteDatabase实例
调用delete()
;
其第一参,表明;
二三参,同update()
的三四参;
Button button = (Button) findViewById(R.id.delete_data);
button.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
SQLiteDatabase db = dbhelper.getWritableDatabase();
db.delete("Book", "pages > ?", new String[]{"500"});
}
});
查询数据
- 通过
query()
进行查询;
其重载方法多,参数复杂,
我们看参数最少(7个参数)的一个;
参数对应内容可参考下表:
(其三四参,同update()
的三四参;)
query()
参数多,
但是多数情况不必要全部参数都用,
指定少数几个参数即可完成查询
(如只传入第一个参数表名,
后面全为null,则查询表中的所有数据);
调用query()
后会返回一个Cursor(n.光标)对象
,
查询到的所有数据
都将从这个对象中取出
;
示例代码:
Button queryButton = (Button) findViewById(R.id.query_data);
queryButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
SQLiteDatabase db = dbhelper.getWritableDatabase();
//查询Book表中所有数据
Cursor cursor = db.query("Book", null,null,null,null,null,null);
if (cursor.moveToFirst()){
do {
//遍历Cursor对象,取出数据并打印
String name = cursor.getString(cursor.getColumnIndex("name") );
String author = cursor.getString(cursor.getColumnIndex("author"));
int pages = cursor.getInt(cursor.getColumnIndex("pages"));
double price = cursor.getDouble(cursor.getColumnIndex("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();
}
});
Cursor实例每次指向返回数据表的一行,
通过moveToFirst()
和moveToNext()
等方法来调节其指向的位置;
令其指向某一行,或者一行一行遍历返回的数据表,
对返回的数据进行处理即可。