最近在看郭神的《第一行代码》,查漏补缺,把基础扎牢一些。今天看到数据库开启事务那,从来没用过事务,从文中摘出来,记录一下。
-------以下都是从书中copy过来的内容
“前面我们已经知道,SQLite数据库是支持事务的,事务的特性可以保证让某一系列的操 作要么全部完成,要么一个都不会完成。那么在什么情况下才需要使用事务呢?想象以下场 景,比如你正在进行一次转账操作,银行会将转账的金额先从你的账户中扣除,然后再向收 款方的账户中添加等量的金额。看上去好像没什么问题吧?可是,如果当你账户中的金额刚 刚被扣除,这时由于一些异常原因导致对方收款失败,这一部分钱就凭空消失了!当然银行 肯定已经充分考虑到了这种情况,它会保证扣钱和收款的操作要么一起成功,要么都不会成 功,而使用的技术当然就是事务了。
接下来我们看一看如何在 Android中使用事务吧,仍然是在 DatabaseTest项目的基础上 进行修改。比如 Book表中的数据都已经很老了,现在准备全部废弃掉替换成新数据,可以 先使用delete()方法将Book表中的数据删除,然后再使用insert()方法将新的数据添加到表中。 我们要保证的是,删除旧数据和添加新数据的操作必须一起完成,否则就还要继续保留原来 的旧数据。修改 activity_main.xml中的代码,如下所示:
……
可以看到,这里又添加了一个按钮,用于进行数据替换操作。然后修改 MainActivity中 的代码,如下所示:
public class MainActivity extends Activity {
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 replaceData = (Button) findViewById(R.id.replace_data);
replaceData.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
SQLiteDatabase db = dbHelper.getWritableDatabase();
db.beginTransaction(); // 开启事务
try {
db.delete("Book", null, null);
if (true) { // 在这里手动抛出一个异常,让事务失败
throw new NullPointerException();
}
ContentValues values = new ContentValues();
values.put("name", "Game of Thrones");
values.put("author", "George Martin");
values.put("pages", 720);
values.put("price", 20.85);
db.insert("Book", null, values);
db.setTransactionSuccessful(); // 事务已经执行成功
} catch (Exception e) {
e.printStackTrace(); }
finally { db.endTransaction(); // 结束事务 } } });
}
}
上述代码就是Android中事务的标准用法,首先调用SQLiteDatabase的beginTransaction() 方法来开启一个事务,然后在一个异常捕获的代码块中去执行具体的数据库操作,当所有的 操作都完成之后,调用 setTransactionSuccessful()表示事务已经执行成功了,最后在 finally 代码块中调用 endTransaction()来结束事务。注意观察,我们在删除旧数据的操作完成后手动 抛出了一个 NullPointerException,这样添加新数据的代码就执行不到了。不过由于事务的存 在,中途出现异常会导致事务的失败,此时旧数据应该是删除不掉的。
现在可以运行一下程序并点击 Replacedata按钮,你会发现,Book表中存在的还是之前 的旧数据。然后将手动抛出异常的那行代码去除,再重新运行一下程序,此时点击一下 Replacedata按钮就会将 Book表中的数据替换成新数据了。
”