版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/wangxuewei111/article/details/45557401
1.创建数据库
SQLiteOpenHelper是一个抽象类,要想使用它就要创建一个自己的帮助类去继承它,SQLiteOpenHelper中有两个抽象方法,分别是onCreate()和onUpgrade(),我们需要重写这两个方法,然后分别在这两个方法中去实现创建、升级数据库的逻辑。
SQLiteOpenHelper中还有两个非常重要的实例方法,getReadableDatabase()和getWritableDatabase().这两个方法都可以创建或打开一个现有的数据库(如果数据库已存在则直接打开,否则创建一个新的数据库),并返回一个可对数据库进行读写操作的对象。不同的是,当数据库不可写入的时候(如磁盘空间已满)getReadableDatabase()方法返回的对象将以只读的方式去打开数据库,而getWritableDatabase()方法则将出现异常.
SQLiteOpenHelper中有两个构造方法可供重写。一般少一点的那个构造方法中接收四个参数。
第一个参数是Context,必须要有它才能对数据库进行操作。
第二个参数是数据库名,创建数据库时使用的就是这里指定的名称。
第三个参数是允许我们在查询数据的时候返回一个自定义的Cursor,一般都是传入null。
第四个参数表示当前数据库的版本号,可用于对数据库进行升级操作。
MyDatabaseHelper.java
package com.king.mydatabasehelper;
import android.content.Context;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteDatabase.CursorFactory;
import android.database.sqlite.SQLiteOpenHelper;
import android.widget.Toast;
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)";
public static final String CREATE_CATEGORY = " create table Category("
+ " id integer primary key autoincrement,"
+ " category_name text,"
+ " catagory_code integer)";
private Context mContext;
public MyDatabaseHelper(Context context, String name,
CursorFactory factory, int version) {
super(context, name, factory, version);
mContext = context;
}
@Override
public void onCreate(SQLiteDatabase db) {
db.execSQL(CREATE_BOOK);
db.execSQL(CREATE_CATEGORY);
Toast.makeText(mContext, "Create success", Toast.LENGTH_SHORT).show();
}
@Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
//强行丢数据库升级,会造成数据丢失
<span style="white-space:pre"> </span>/*<span style="white-space:pre"> </span>db.execSQL(" drop table if exists Book");
<span style="white-space:pre"> </span>db.execSQL(" drop table if exists Category");
<span style="white-space:pre"> </span>onCreate(db);*/
<span style="white-space:pre"> </span>switch(oldVersion){
<span style="white-space:pre"> </span>case 1:
<span style="white-space:pre"> </span>db.execSQL(CREATE_CATEGORY);
<span style="white-space:pre"> </span>case 2:
<span style="white-space:pre"> </span>db.execSQL("alert table Book add column catagory_id integer");
<span style="white-space:pre"> </span>default:
<span style="white-space:pre"> </span>}
}
}
这里要注意一个细节,switch中每一个case的最后都是没有使用break的,这是为了保证在跨版本升级的时候每一次的数据库修改都能被全部执行到。比如用户当前是从第二版程序到第三版程序的,那么case2中的逻辑就会执行。而如果用户是直接从第一版程序升级到第三版程序的,那么case1和case2中的逻辑都会执行,使用这种方式来维护数据库的升级,不管版本怎样更新,都可以保证数据库的表结构是最新的,而且表中的数据也不会丢失。
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
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/query_data"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="Query data"
/>
<!-- 事务 -->
<Button
android:id="@+id/replace_data"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="Replace data"
/>
</LinearLayout>
MainActivity.java
<span style="font-size:14px;">package com.king.mydatabasehelper;
import android.support.v7.app.ActionBarActivity;
import android.content.ContentValues;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
import android.os.Bundle;
import android.util.Log;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
public class MainActivity extends ActionBarActivity {
private MyDatabaseHelper dbHelper;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
/*
* 创建数据库
*
* */
// dbHelper = new MyDatabaseHelper(this, "BookStore.db", null, 1);
<strong>dbHelper = new MyDatabaseHelper(this, "BookStore.db", null, 2);</strong>
Button createDatabase = (Button) findViewById(R.id.create_database);
createDatabase.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
dbHelper.getWritableDatabase();
}
});
/*
* 添加数据
*
* */
Button addData = (Button) findViewById(R.id.add_data);
addData.setOnClickListener(new 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);
values.clear();
}
});
/*
* 更新数据
*
* */
Button updateData = (Button) findViewById(R.id.update_data);
updateData.setOnClickListener(new 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"});
}
});
/*
* 删除数据
*
* */
Button deleteData = (Button) findViewById(R.id.delete_data);
deleteData.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
SQLiteDatabase db = dbHelper.getWritableDatabase();
db.delete("Book", "page > ?",new String[]{"500"});
}
});
/*
* 查询数据
*
* */
Button queryData = (Button) findViewById(R.id.query_data);
queryData.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
SQLiteDatabase db = dbHelper.getWritableDatabase();
//查询Book表中的所有数据
Cursor cursor = db.query("Book", null, null, null, null, null, null);
//调用它的moveToFirst()方法将数据的指针移动到第一行的位置</span>
<span style="font-size:14px;"><span style="white-space:pre"> </span>if(cursor.moveToFirst()){
do {
//遍历Cursor对象,取出数据并打印,通过getColumnIndex()方法获取到某一列在表中对应的位置索引</span>
<span style="font-size:14px;"><span style="white-space:pre"> </span>//然后将这个索引传入到相应的取值方法中,就可以得到从数据库中读取到的数据了
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();
}
});
/*
<span style="white-space:pre"> </span> * 事务
<span style="white-space:pre"> </span> *
<span style="white-space:pre"> </span> * */
<span style="white-space:pre"> </span>Button replaceData = (Button) findViewById(R.id.replace_data);
<span style="white-space:pre"> </span>replaceData.setOnClickListener(new OnClickListener() {
<span style="white-space:pre"> </span>
<span style="white-space:pre"> </span>@Override
<span style="white-space:pre"> </span>public void onClick(View v) {
<span style="white-space:pre"> </span>SQLiteDatabase db = dbHelper.getWritableDatabase();
<span style="white-space:pre"> </span>db.beginTransaction();//开启事务
<span style="white-space:pre"> </span>try {
<span style="white-space:pre"> </span>db.delete("Book", null, null);
<span style="white-space:pre"> </span>if(true){
<span style="white-space:pre"> </span>//在这里手动抛出一个异常,让事务失败
<span style="white-space:pre"> </span>throw new NullPointerException();
<span style="white-space:pre"> </span>}
<span style="white-space:pre"> </span>ContentValues values = new ContentValues();
<span style="white-space:pre"> </span>values.put("name", "Game of Thrones");
<span style="white-space:pre"> </span>values.put("author", "George Martin");
<span style="white-space:pre"> </span>values.put("pages", 720);
<span style="white-space:pre"> </span>values.put("price", 20.85);
<span style="white-space:pre"> </span>db.insert("Book",null,values);
<span style="white-space:pre"> </span>//事务已经执行成功
<span style="white-space:pre"> </span>db.setTransactionSuccessful();
<span style="white-space:pre"> </span>
<span style="white-space:pre"> </span>} catch (Exception e) {
<span style="white-space:pre"> </span>e.printStackTrace();
<span style="white-space:pre"> </span>}finally{
<span style="white-space:pre"> </span>//结束事务
<span style="white-space:pre"> </span>db.endTransaction();
<span style="white-space:pre"> </span>}
<span style="white-space:pre"> </span>}
<span style="white-space:pre"> </span>});
}
}</span><span style="font-size:18px;">
</span>
首先调用SQLiteDatabase的beginTransation()方法来开启一个事务,然后在一个异常捕获的代码块中去执行具体的数据库操作,当所有的操作都完成之后,调用setTransactionSuccessful()表示事务已经执行成功了,最后早finally代码块中调用endTransaction()来结束事务。我们在删除旧数据的操作完成后手动跑出了一个NullPointerException,这样添加新数据的代码就执行不到了,不过由于事务的存在,中途出现异常会导致事务的失败,此时旧数据应该是删除不掉的。
2.使用SQL操作数据库
添加数据:
db.execSQL(" insert into Book (name,author,pages,price) values(?,?,?,?)",new String[]{"The Da Vinci Code","Dan Brown","454","16.96"});
更新数据:
db.execSQL(" update Book set price=? where name=?",new String[]{"10.99","The Da Vinci Code"});
删除数据:
db.execSQL("delete from Book where pages > ?",new Srting[]{"500"});
查询数据:
db.rawQuery("select * from Book",null);
可以看到,除了查询数据的时候用的是SQLiteDatabase的rawQuery()方法,其他的操作都是调用execSQL()方法。以上延时的几种方法,执行结果会和前面几小节中我们学习的CRUD操作的结果完全相同,选择使用哪一种方式就看你的个人爱好了。