喷泉的高度不会超过它的源头;一个人的事业也是这样,他的成就绝不会超过自己的信念。—— 林 肯
本讲内容:SQLiteDatabse数据库
一、SQLiteOpenHelper类
SQLiteOpenHelper是SQLiteDatabse的一个帮助类,用来管理数据的创建和版本更新。一般的用法是定义一个类继承SQLiteOpenHelper,并实现两个回调方法,OnCreate()和onUpgrade()来创建和更新数据库。SQLiteOpenHelper中有两个重要的实例方法,getWritableDatabase()和getReadableDatabase()。这两个方法都可以创建或打开一个现有的数据库(如果数据库已存在则直接打开,否则创建一个新的数据库),并返回一个可对数据库进行读写操作的对象。不同的的是,当数据库不可写入时(如磁盘空间已满)getReadableDatabase()方法返回的对象将以只读的方式去打开数据库,而getWritableDatabase()方法则将出现异常。
示例一:创建一个名为BoodStore.db的数据库,然后在这个数据库中新建一张book表。表中有id(主键)、作者、价格、页数和书名等列。
运行程序,点击按钮,此时BoodStore.db数据库和book表都已经创建成功了,当你再次点击按钮时,不会再有Toast弹出。切换到DDMS->File Explorer /data/data/com.example.databasetext01/databases/目录下,可以看到生成了一个BoodStore.db文件,book表是无法通过File Explorer看到的,可以使用adb shell来对数据库和表的创建情况进行检查
下面是res/layout/activity_main.xml 布局文件:
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent" >
<Button
android:id="@+id/create_database"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="Create database" />
</RelativeLayout>
下面是MyDatabaseHelper.java文件:
public class MyDatabaseHelper extends SQLiteOpenHelper{
private Context mContext;
public static final String CREATE_BOOK="create table book(id integer primary key autoincrement,author text,price real,pages integer,name text)";
//四个参数的构造函数
public MyDatabaseHelper(Context context, String name,CursorFactory factory, int version) {
super(context, name, factory, version);
mContext=context;
}
//回调函数,第一次创建数据库时才会调用此函数
public void onCreate(SQLiteDatabase db) {
db.execSQL(CREATE_BOOK);
Toast.makeText(mContext, "Create succeeded", Toast.LENGTH_LONG).show();
}
//回调函数,当你构造DBHelper的传递的Version与之前的Version不同时调用此函数
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
}
}
下面是MainActivity.java主界面文件:
public class MainActivity extends Activity {
private MyDatabaseHelper dbHelper;
private Button createDatabase;
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
//指定数据库名为BoodStore.db,版本号为1
dbHelper=new MyDatabaseHelper(this, "BoodStore.db", null, 1);
createDatabase=(Button) findViewById(R.id.create_database);
createDatabase.setOnClickListener(new OnClickListener() {
public void onClick(View v) {
dbHelper.getWritableDatabase();//创建数据库
}
});
}
}
示例二:升级数据库
BoodStore.db数据库已经有一张book表用于存放书的各种详细数据,我们再添加一张Category表用于记录书籍的分类。Category表中有id(主键)、分类名和分类代码。
下面是MyDatabaseHelper.java文件:
public class MyDatabaseHelper extends SQLiteOpenHelper{
private Context mContext;
public static final String CREATE_BOOK="create table book(id integer primary key autoincrement,author text,price real,pages integer,name text)";
public static final String CREATE_CATEGORY="create table Category(id integer primary key autoincrement,category_name text,category_code integer)";
//四个参数的构造函数
public MyDatabaseHelper(Context context, String name,CursorFactory factory, int version) {
super(context, name, factory, version);
mContext=context;
}
//回调函数,第一次创建数据库时才会调用此函数
public void onCreate(SQLiteDatabase db) {
db.execSQL(CREATE_BOOK);
db.execSQL(CREATE_CATEGORY);
Toast.makeText(mContext, "Create succeeded", Toast.LENGTH_LONG).show();
}
//回调函数,当你构造DBHelper的传递的Version与之前的Version不同时调用此函数
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
//先将已经存在的表删除,因为如果在创建时发现这张表已经存在了,会直接报错
db.execSQL("drop table if exists book");
onCreate(db);
}
}
下面是MainActivity.java主界面文件:
public class MainActivity extends Activity {
private MyDatabaseHelper dbHelper;
private Button createDatabase;
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
//指定数据库名为BoodStore.db,版本号为1
dbHelper=new MyDatabaseHelper(this, "BoodStore.db", null, 2">);
createDatabase=(Button) findViewById(R.id.create_database);
createDatabase.setOnClickListener(new OnClickListener() {
public void onClick(View v) {
dbHelper.getWritableDatabase();//创建数据库
}
});
}
}
示例三:添加数据
SQLiteOpenHelper的getWritableDatabase()和getReadableDatabase()方法不仅可以用于创建和升级数据库,还会返回一个SQLiteDatabse对象,借助这个对象就可以对数据进行CRUD操作了
点击按钮,添加两条数据
记得加分号
下面是res/layout/activity_main.xml 布局文件:
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<Button
android:id="@+id/create_database"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="Create database" />
<Button
android:id="@+id/add_data"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="Add data"/>
</LinearLayout>
下面是MainActivity.java主界面文件:
public class MainActivity extends Activity {
private MyDatabaseHelper dbHelper;
private Button createDatabase;
private Button addData;
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
//指定数据库名为BoodStore.db,版本号为1
dbHelper=new MyDatabaseHelper(this, "BoodStore.db", null, 2);
createDatabase=(Button) findViewById(R.id.create_database);
createDatabase.setOnClickListener(new OnClickListener() {
public void onClick(View v) {
dbHelper.getWritableDatabase();//创建数据库
}
});
addData=(Button) findViewById(R.id.add_data);
addData.setOnClickListener(new OnClickListener() {
public void onClick(View v) {
//获取SQLiteDatabase对象
SQLiteDatabase db=dbHelper.getWritableDatabase();
//使用ContentValues来对要添加的数据进行组装
ContentValues values=new ContentValues();
//开始组装第一条数据
values.put("name", "The Da Vinci Code");
values.put("author", "Dan Brown");
values.put("pages", 554);
values.put("price", 16.97);
//第一个参数表名,第二个参数null,第三个参数ContentValues对象
db.insert("book", null, values);//插入第一条数据
//开始组装第二条数据
values.put("name", "The Lost Symbol");
values.put("author", "Dan Brown");
values.put("pages", 1001);
values.put("price", 36.47);
db.insert("book", null, values);//插入第二条数据
Toast.makeText(MainActivity.this, "添加数据成功", Toast.LENGTH_LONG).show();
}
});
}
}
示例四:更新数据
点击按钮,更新数据
下面是MainActivity.java主界面文件:
public class MainActivity extends Activity implements OnClickListener{
private MyDatabaseHelper dbHelper;
private Button createDatabase;
private Button addData;
private Button updateData;
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
//指定数据库名为BoodStore.db,版本号为1
dbHelper=new MyDatabaseHelper(this, "BoodStore.db", null, 2);
createDatabase=(Button) findViewById(R.id.create_database);
addData=(Button) findViewById(R.id.add_data);
updateData=(Button) findViewById(R.id.update_data);
createDatabase.setOnClickListener(this);
addData.setOnClickListener(this);
updateData.setOnClickListener(this);
}
public void onClick(View v) {
//获取SQLiteDatabase对象
SQLiteDatabase db=dbHelper.getWritableDatabase();
//使用ContentValues来对要添加的数据进行组装
ContentValues values=new ContentValues();
switch (v.getId()) {
case R.id.create_database:
dbHelper.getWritableDatabase();//创建数据库
break;
case R.id.add_data:
//开始组装第一条数据
values.put("name", "The Da Vinci Code");
values.put("author", "Dan Brown");
values.put("pages", 554);
values.put("price", 16.97);
//第一个参数表名,第二个参数null,第三个参数ContentValues对象
db.insert("book", null, values);//插入第一条数据
//开始组装第二条数据
values.put("name", "The Lost Symbol");
values.put("author", "Dan Brown");
values.put("pages", 1001);
values.put("price", 36.47);
db.insert("book", null, values);//插入第二条数据
Toast.makeText(MainActivity.this, "添加数据成功", Toast.LENGTH_LONG).show();
break;
case R.id.update_data:
values.put("price", 10.99);
//第一個參數表名,第二个参数ContentValues对象,把要更新数据在這里組裝進去,第三、第四个参数用于去约束更新某一行或几行中的数据,
//不指定的话默认就是更新所有行,第三个参数对应的是SQL语句的where部分,表示去更新所有name等于?的行,而?是一个点位符,
//可以通过第四个参数提供的一个字符串数组为第三个参数中的第个点位符指定相应的内容。
//这里表示将名字是The Da Vinci Code的这本书的价格改成10.99
db.update("book", values, "name=?", new String[] {"The Da Vinci Code"});
Toast.makeText(MainActivity.this, "更新数据成功", Toast.LENGTH_LONG).show();
break;
}
}
}
示例五:删除数据
点击按钮,删除数据
下面是MainActivity.java主界面文件:
public class MainActivity extends Activity implements OnClickListener{
private MyDatabaseHelper dbHelper;
private Button createDatabase;
private Button addData;
private Button updateData;
private Button deleteData;
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
//指定数据库名为BoodStore.db,版本号为1
dbHelper=new MyDatabaseHelper(this, "BoodStore.db", null, 2);
createDatabase=(Button) findViewById(R.id.create_database);
addData=(Button) findViewById(R.id.add_data);
updateData=(Button) findViewById(R.id.update_data);
deleteData=(Button) findViewById(R.id.delete_data);
createDatabase.setOnClickListener(this);
addData.setOnClickListener(this);
updateData.setOnClickListener(this);
deleteData.setOnClickListener(this);
}
public void onClick(View v) {
//获取SQLiteDatabase对象
SQLiteDatabase db=dbHelper.getWritableDatabase();
//使用ContentValues来对要添加的数据进行组装
ContentValues values=new ContentValues();
switch (v.getId()) {
case R.id.create_database:
dbHelper.getWritableDatabase();//创建数据库
break;
case R.id.add_data:
//开始组装第一条数据
values.put("name", "The Da Vinci Code");
values.put("author", "Dan Brown");
values.put("pages", 554);
values.put("price", 16.97);
//第一个参数表名,第二个参数null,第三个参数ContentValues对象
db.insert("book", null, values);//插入第一条数据
//开始组装第二条数据
values.put("name", "The Lost Symbol");
values.put("author", "Dan Brown");
values.put("pages", 1001);
values.put("price", 36.47);
db.insert("book", null, values);//插入第二条数据
Toast.makeText(MainActivity.this, "添加数据成功", Toast.LENGTH_LONG).show();
break;
case R.id.update_data:
values.put("price", 10.99);
//第一個參數表名,第二个参数ContentValues对象,把要更新数据在這里組裝進去,第三、第四个参数用于去约束更新某一行或几行中的数据,
//不指定的话默认就是更新所有行,第三个参数对应的是SQL语句的where部分,表示去更新所有name等于?的行,而?是一个点位符,
//可以通过第四个参数提供的一个字符串数组为第三个参数中的第个点位符指定相应的内容。
//这里表示将名字是The Da Vinci Code的这本书的价格改成10.99
db.update("book", values, "name=?", new String[] {"The Da Vinci Code"});
Toast.makeText(MainActivity.this, "更新数据成功", Toast.LENGTH_LONG).show();
break;
case R.id.delete_data:
//第一個參數表名,第二、第三个参数用于去约束刪除某一行或几行中的数据,不指定的话默认就是刪除所有行
db.delete("book", "pages>?", new String[] {"800"});
Toast.makeText(MainActivity.this, "刪除数据成功", Toast.LENGTH_LONG).show();
}
}
}
示例六:查询数据
点击按钮,查询数据
下面是res/layout/activity_main.xml 布局文件:
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<Button
android:id="@+id/create_database"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="Create database" />
<Button
android:id="@+id/add_data"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="Add data"/>
<Button
android:id="@+id/update_data"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="Update data"/>
<Button
android:id="@+id/delete_data"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="Delete data"/>
<Button
android:id="@+id/quety_data"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="Quety data"/>
</LinearLayout>
下面是MainActivity.java主界面文件:
public class MainActivity extends Activity implements OnClickListener{
private static final String TAG="MainActivity";
private MyDatabaseHelper dbHelper;
private Button createDatabase;
private Button addData;
private Button updateData;
private Button deleteData;
private Button quetyData;
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
//指定数据库名为BoodStore.db,版本号为1
dbHelper=new MyDatabaseHelper(this, "BoodStore.db", null, 2);
createDatabase=(Button) findViewById(R.id.create_database);
addData=(Button) findViewById(R.id.add_data);
updateData=(Button) findViewById(R.id.update_data);
deleteData=(Button) findViewById(R.id.delete_data);
quetyData=(Button) findViewById(R.id.quety_data);
createDatabase.setOnClickListener(this);
addData.setOnClickListener(this);
updateData.setOnClickListener(this);
deleteData.setOnClickListener(this);
quetyData.setOnClickListener(this);
}
public void onClick(View v) {
//获取SQLiteDatabase对象
SQLiteDatabase db=dbHelper.getWritableDatabase();
//使用ContentValues来对要添加的数据进行组装
ContentValues values=new ContentValues();
switch (v.getId()) {
case R.id.create_database:
dbHelper.getWritableDatabase();//创建数据库
break;
case R.id.add_data:
//开始组装第一条数据
values.put("name", "The Da Vinci Code");
values.put("author", "Dan Brown");
values.put("pages", 554);
values.put("price", 16.97);
//第一个参数表名,第二个参数null,第三个参数ContentValues对象
db.insert("book", null, values);//插入第一条数据
//开始组装第二条数据
values.put("name", "The Lost Symbol");
values.put("author", "Dan Brown");
values.put("pages", 1001);
values.put("price", 36.47);
db.insert("book", null, values);//插入第二条数据
Toast.makeText(MainActivity.this, "添加数据成功", Toast.LENGTH_LONG).show();
break;
case R.id.update_data:
values.put("price", 10.99);
//第一個參數表名,第二个参数ContentValues对象,把要更新数据在這里組裝進去,第三、第四个参数用于去约束更新某一行或几行中的数据,
//不指定的话默认就是更新所有行,第三个参数对应的是SQL语句的where部分,表示去更新所有name等于?的行,而?是一个点位符,
//可以通过第四个参数提供的一个字符串数组为第三个参数中的第个点位符指定相应的内容。
//这里表示将名字是The Da Vinci Code的这本书的价格改成10.99
db.update("book", values, "name=?", new String[] {"The Da Vinci Code"});
Toast.makeText(MainActivity.this, "更新数据成功", Toast.LENGTH_LONG).show();
break;
case R.id.delete_data:
//第一個參數表名,第二、第三个参数用于去约束刪除某一行或几行中的数据,不指定的话默认就是刪除所有行
db.delete("book", "pages>?", new String[] {"800"});
Toast.makeText(MainActivity.this, "刪除数据成功", Toast.LENGTH_LONG).show();
break;
case R.id.quety_data:
//查詢Book表中所有的數據,調用quety()方法会返回一个Cursor对象,查询到所有数据都是从这个对象中取出的
//第一个参数表名,第二个参数用于指定查询哪几列,如果不指定则默认查询所有列,第三、四个参数用于去约束查询某一行或几行中的数据,
//不指定的话默认就是查询所有行的数据,第五个参数用于指定需要去group by的列,不指定则表示不对查询结果进行group by操作,
//第六个参数用于对group by之后的数据进行进一步的过滤,不指定则表示不进行过滤,第七个参数用于指定查询的结果的排序方式,不指定则表示使用默认的排序方式。
Cursor cursor=db.query("book", null, null, null, null, null, null);
if(cursor.moveToFirst()){//將数据的指针移动到第一行的位置
do{
//遍历Cursor对象,取出数据并打印,getColumnIndex()方法获取到某一列在表中对应的的位置索引
//然后將这个索引传入到相应的的取值方法中,就可以得到从数据库中读取的数据了
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
Toast.makeText(MainActivity.this, "查詢数据成功", Toast.LENGTH_LONG).show();
break;
}
}
}
示例七:使用事务
SQLite数据库是支持事务的,事务的特性可以保证让某一系列的操作要么全部完成,要么一个都不会完成。
譬如:在book中删除旧数据和添加新数据必须一起完成。
运行程序,点击按钮
下面是MainActivity.java主界面文件:
public class MainActivity extends Activity implements OnClickListener{
private static final String TAG="MainActivity";
private MyDatabaseHelper dbHelper;
private Button createDatabase;
private Button addData;
private Button updateData;
private Button deleteData;
private Button quetyData;
private Button replaceData;
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
//指定数据库名为BoodStore.db,版本号为1
dbHelper=new MyDatabaseHelper(this, "BoodStore.db", null, 2);
createDatabase=(Button) findViewById(R.id.create_database);
addData=(Button) findViewById(R.id.add_data);
updateData=(Button) findViewById(R.id.update_data);
deleteData=(Button) findViewById(R.id.delete_data);
quetyData=(Button) findViewById(R.id.quety_data);
replaceData=(Button) findViewById(R.id.replace_data);
createDatabase.setOnClickListener(this);
addData.setOnClickListener(this);
updateData.setOnClickListener(this);
deleteData.setOnClickListener(this);
quetyData.setOnClickListener(this);
replaceData.setOnClickListener(this);
}
public void onClick(View v) {
//获取SQLiteDatabase对象
SQLiteDatabase db=dbHelper.getWritableDatabase();
//使用ContentValues来对要添加的数据进行组装
ContentValues values=new ContentValues();
switch (v.getId()) {
case R.id.create_database:
dbHelper.getWritableDatabase();//创建数据库
break;
case R.id.add_data:
//开始组装第一条数据
values.put("name", "The Da Vinci Code");
values.put("author", "Dan Brown");
values.put("pages", 554);
values.put("price", 16.97);
//第一个参数表名,第二个参数null,第三个参数ContentValues对象
db.insert("book", null, values);//插入第一条数据
//开始组装第二条数据
values.put("name", "The Lost Symbol");
values.put("author", "Dan Brown");
values.put("pages", 1001);
values.put("price", 36.47);
db.insert("book", null, values);//插入第二条数据
Toast.makeText(MainActivity.this, "添加数据成功", Toast.LENGTH_LONG).show();
break;
case R.id.update_data:
values.put("price", 10.99);
//第一個參數表名,第二个参数ContentValues对象,把要更新数据在這里組裝進去,第三、第四个参数用于去约束更新某一行或几行中的数据,
//不指定的话默认就是更新所有行,第三个参数对应的是SQL语句的where部分,表示去更新所有name等于?的行,而?是一个点位符,
//可以通过第四个参数提供的一个字符串数组为第三个参数中的第个点位符指定相应的内容。
//这里表示将名字是The Da Vinci Code的这本书的价格改成10.99
db.update("book", values, "name=?", new String[] {"The Da Vinci Code"});
Toast.makeText(MainActivity.this, "更新数据成功", Toast.LENGTH_LONG).show();
break;
case R.id.delete_data:
//第一個參數表名,第二、第三个参数用于去约束刪除某一行或几行中的数据,不指定的话默认就是刪除所有行
db.delete("book", "pages>?", new String[] {"800"});
Toast.makeText(MainActivity.this, "刪除数据成功", Toast.LENGTH_LONG).show();
break;
case R.id.quety_data:
//查詢Book表中所有的數據,調用quety()方法会返回一个Cursor对象,查询到所有数据都是从这个对象中取出的
//第一个参数表名,第二个参数用于指定查询哪几列,如果不指定则默认查询所有列,第三、四个参数用于去约束查询某一行或几行中的数据,
//不指定的话默认就是查询所有行的数据,第五个参数用于指定需要去group by的列,不指定则表示不对查询结果进行group by操作,
//第六个参数用于对group by之后的数据进行进一步的过滤,不指定则表示不进行过滤,第七个参数用于指定查询的结果的排序方式,不指定则表示使用默认的排序方式。
Cursor cursor=db.query("book", null, null, null, null, null, null);
if(cursor.moveToFirst()){//將数据的指针移动到第一行的位置
do{
//遍历Cursor对象,取出数据并打印,getColumnIndex()方法获取到某一列在表中对应的的位置索引
//然后將这个索引传入到相应的的取值方法中,就可以得到从数据库中读取的数据了
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
Toast.makeText(MainActivity.this, "查詢数据成功", Toast.LENGTH_LONG).show();
break;
case R.id.replace_data:
db.beginTransaction();//开启事务
try {
db.delete("book", null, null);
// if(true){
// //在这里手动抛出一个异常,让事务失败
// throw new NullPointerException();
// }
values.put("name", "Game of Thrones");
values.put("author", "George Martin");
values.put("pages", 720);
values.put("price", 30.98);
db.insert("book", null, values);
db.setTransactionSuccessful();//事务已经执行成功
} catch (Exception e) {
e.printStackTrace();
}finally{
db.endTransaction();//结束事务
}
Toast.makeText(MainActivity.this, "事務替換数据成功", Toast.LENGTH_LONG).show();
break;
}
}
}
Take your time and enjoy it 要原码的、路过的、学习过的请留个言,顶个呗~~