事务处理流程
- 开启事务:在进行转账操作前,开启一个SQLite事务。这确保后续的所有数据库操作都在同一个事务上下文内。
- 执行操作:在事务内执行多个数据库操作,如更新转账方账户余额(减少金额)和接收方账户余额(增加金额)。
- 提交事务:如果所有操作都成功完成,提交事务,这会使所有在事务内的修改永久生效。
- 回滚事务:如果在事务执行过程中任何一个操作失败,回滚事务,撤销所有在事务内已经执行的操作,确保数据回到事务开始前的状态。
Flutter代码示例
import 'package:sqflite/sqflite.dart';
import 'package:path/path.dart';
class DatabaseHelper {
static final DatabaseHelper instance = DatabaseHelper._init();
static Database? _database;
DatabaseHelper._init();
Future<Database> get database async {
if (_database != null) return _database!;
_database = await _initDB('finance.db');
return _database!;
}
Future<Database> _initDB(String filePath) async {
final dbPath = await getDatabasesPath();
final path = join(dbPath, filePath);
return await openDatabase(path, version: 1, onCreate: _createDB);
}
Future<void> _createDB(Database db, int version) async {
const idType = 'INTEGER PRIMARY KEY AUTOINCREMENT';
const textType = 'TEXT NOT NULL';
const integerType = 'INTEGER NOT NULL';
await db.execute('''
CREATE TABLE accounts (
id $idType,
accountName $textType,
balance $integerType
)
''');
}
Future<void> transfer(int fromAccountId, int toAccountId, int amount) async {
final db = await instance.database;
try {
await db.transaction((txn) async {
// 减少转账方余额
await txn.rawUpdate(
'UPDATE accounts SET balance = balance -? WHERE id =?',
[amount, fromAccountId],
);
// 增加接收方余额
await txn.rawUpdate(
'UPDATE accounts SET balance = balance +? WHERE id =?',
[amount, toAccountId],
);
});
} catch (e) {
// 捕获异常并处理,回滚事务
print('Transaction failed: $e');
rethrow;
}
}
}
使用示例
void main() async {
final dbHelper = DatabaseHelper.instance;
await dbHelper.database;
try {
await dbHelper.transfer(1, 2, 100);
print('Transfer successful');
} catch (e) {
print('Transfer failed: $e');
}
}
错误处理机制
- try - catch块:在
transfer
方法中,使用try - catch
块来捕获事务执行过程中的任何异常。如果捕获到异常,打印错误信息并重新抛出异常,以便调用者可以进一步处理。
- 事务内操作失败:如果在事务内的任何一个
rawUpdate
操作失败,transaction
方法会自动回滚事务,确保数据一致性。调用者在main
函数中的try - catch
块可以捕获到错误并进行相应处理。