Android SQLite數據庫之事務的學習


SQLite是Android系統內置的一款輕量級的關系型數據庫,它的運算速度非常快,占用資源很少,通常只需要幾百K的內存就足夠了。SQLite不僅支持標准的SQL語法,還遵循了數據庫的ACID事務。

模擬一個應用場景:進行一次轉賬操作,銀行會將轉賬的金額先從你的賬戶中扣除,然后再向收款方的賬戶中添加等量的金額。看上去好像沒有什么問題,可是當你的賬戶的金額剛剛被扣除,這是由於一些異常原因導致對方收款失敗(比如突然斷電),這一部分錢就憑空消失了,當然銀行自然會考慮到這個問題,它會保證扣錢和收款的操作要么一起完成,要么都不會成功,而使用的技術就是事物了。

Android為了讓我們能夠更加方便的管理數據庫,專門提供了一個SQLiteOpenHelper輔助類,借助這個類我們可以很方便的對數據庫進行創建和升級。由於SQLiteOpenHelper是一個抽象類,我們需要自己創一個輔助類去繼承他。

創建MyDatabaseHelper

package com.tonycheng.databasetest;

import android.content.Context;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteOpenHelper;
import android.widget.Toast;

/**
 * Created by tonycheng on 2015/6/27.
 */
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," +
            "category_id 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) {
        db.execSQL(CREATE_BOOK);
        Toast.makeText(mContext, "Create succeeded", Toast.LENGTH_SHORT).show();
    }

    @Override
    public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
    }

}

寫一個簡單的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:paddingLeft="@dimen/activity_horizontal_margin"
    android:paddingRight="@dimen/activity_horizontal_margin"
    android:paddingTop="@dimen/activity_vertical_margin"
    android:paddingBottom="@dimen/activity_vertical_margin"
    android:orientation="vertical"
    tools:context=".MainActivity">

    <Button
        android:id="@+id/create_database"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="Create Database"
        />
    <Button
        android:id="@+id/replace_data"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="Replace data"
        />

</LinearLayout>

最后在MainActivity中修改代碼:

第一步創建一個數據庫:

package com.tonycheng.databasetest;

import android.content.ContentValues;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
import android.support.v7.app.ActionBarActivity;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.widget.Button;


public class MainActivity extends ActionBarActivity {
    private MyDatabaseHelper dbHelper;
    private Button btn_createDatabase;
    private Button btn_raplaceData;

    private static final String TAG = "MainActivity";

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        dbHelper = new MyDatabaseHelper(this,"BookStore.db",null,1);
        btn_createDatabase = (Button) findViewById(R.id.create_database);
        btn_raplaceData = (Button) findViewById(R.id.replace_data);
        btn_createDatabase.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                dbHelper.getWritableDatabase();
            }
        });
    }
}

onCreat()方法中構建了一個MyDatabaseHelper對象,並通過構造函數的參數將數據庫名指定為BookStore.db,版本號指定為1。然后在按鈕的onClick事件中調用getWritableDatabase()方法創數據庫。

向BookStore.db數據庫中添加一條數據:在添加一個Add Data按鈕

 btn_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",510); values.put("price", 19.95); db.insert("book", null, values);
//第二種方法
//使用SQL插入數據(同理設用於其他集中操作) //兩種添加數據的方法,如果你覺得上面一種方法太繁瑣,就是用SQL語句來創建,他們的效果是一樣的 db.execSQL("insert into book(name,author,pages,price) values(?,?,?,?)",new String[]{ "The Da Vinci Code","Dan Brown","510","19.95" }); } });

這樣數據庫中就有一條數據了,我們老進行事物操作:我們從book表中刪除這條數據,再添加一條新的數據:

 /**
         * 使用事物來進行數據庫操作,兩種操作要么都完成,要么都失敗(事物)
         */
        btn_raplaceData.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                SQLiteDatabase db = dbHelper.getWritableDatabase();
                db.beginTransaction();//開啟事物
                try {
                    db.delete("book",null,null);
                    if (true){
                        //這里手動拋出一個異常,讓事物失敗
                      //  throw new NullPointerException();//由於我們手動拋出了一個異常,這樣添加數據的代碼就無法執行了,但是由於事物的存在,此時舊數據也無法刪除
                    }
                    db.execSQL("insert into book(name,author,pages,price) values(?,?,?,?)", new String[]{
                            "android ", "tonycheng", "550", "79"
                    });
                    db.setTransactionSuccessful();
                }finally {
                    db.endTransaction();
                }
            }
        });

運行上面的代碼,發現表中的數據沒有被刪除,這是由於我們啟用了事務,故意手動拋出了一個異常,導致舊數據也無法刪除,如果沒有啟用事務,book表中的舊數據時會被刪除的,而由於異常,添加數據的代碼就無法執行。而這樣在一些場合下是會出大問題的。由此,事務的重要性就體現出來了。至此,我們事務的一個簡單的模擬就完成了。

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM