• 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表中的旧数据时会被删除的,而由于异常,添加数据的代码就无法执行。而这样在一些场合下是会出大问题的。由此,事务的重要性就体现出来了。至此,我们事务的一个简单的模拟就完成了。

  • 相关阅读:
    Eclipse检出原MyEclipse项目后 javax.servlet.http相关类都报错【我,体现着一类jar包问题的处理方法】
    Tomcat中加载不到项目 项目构建Deployment Assembly报错:The given project is not a virtual component project
    Unity手游之路<十一>资源打包Assetbundle
    Unity手游之路<十二>手游资源热更新策略探讨
    Unity手游之路<十三>手游代码更新策略探讨
    观察者(Observer)模式
    访问者(Visitor)模式
    设计模式(15)-Facade Pattern
    使用Monitor调试Unity3D Android程序日志输出(非DDMS和ADB)
    思维导图快捷键
  • 原文地址:https://www.cnblogs.com/Free-Thinker/p/6991405.html
Copyright © 2020-2023  润新知