面试题答案
一键面试-
使用事务确保数据一致性和完整性
- 在Flutter中使用
sqflite
库来操作SQLite数据库。事务可以将多个数据库操作作为一个原子单元执行,要么全部成功,要么全部失败。 - 关键步骤及作用:
- 开启事务:通过
database.transaction
方法开启一个事务。这一步骤的作用是告诉数据库,接下来的操作将作为一个整体进行处理,如果其中任何一个操作失败,整个事务将回滚。 - 执行操作:在事务闭包内执行增删改查等数据库操作。这些操作会暂时存储在事务中,不会立即提交到数据库。
- 提交事务:如果所有操作都成功,通过
transaction.commit()
方法提交事务,将所有操作永久保存到数据库。 - 回滚事务:如果在事务执行过程中任何操作抛出异常,事务会自动回滚,撤销所有已执行的操作,确保数据库状态不变。
- 开启事务:通过
- 在Flutter中使用
-
处理并发操作导致的冲突
- 使用同步机制:在Flutter中,可以使用
dart:async
库中的Lock
来同步对数据库的访问。Lock
可以确保同一时间只有一个页面的操作能够进入事务,避免并发冲突。 - 关键步骤及作用:
- 创建Lock实例:在应用的合适位置(比如数据库操作的管理类中)创建一个
Lock
实例。 - 获取锁:在进行数据库事务操作前,使用
await lock.lock()
获取锁。这一步确保当前只有一个页面能够进行数据库操作,其他页面需要等待锁的释放。 - 释放锁:在事务完成(无论是成功提交还是回滚)后,使用
lock.unlock()
释放锁,让其他页面可以获取锁并进行操作。
- 创建Lock实例:在应用的合适位置(比如数据库操作的管理类中)创建一个
- 使用同步机制:在Flutter中,可以使用
-
代码架构示例
import 'package:sqflite/sqflite.dart';
import 'package:path/path.dart';
import 'package:async/async.dart';
class DatabaseHelper {
static final DatabaseHelper instance = DatabaseHelper._init();
static Database? _database;
final Lock lock = Lock();
DatabaseHelper._init();
Future<Database> get database async {
if (_database != null) return _database!;
_database = await _initDB('my_database.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: (Database db, int version) async {
await db.execute('''
CREATE TABLE users (
id INTEGER PRIMARY KEY AUTOINCREMENT,
name TEXT NOT NULL,
age INTEGER NOT NULL
)
''');
},
);
}
Future<void> insertUser(Map<String, dynamic> user) async {
await lock.lock();
try {
final db = await instance.database;
await db.transaction((txn) async {
await txn.insert('users', user);
});
} finally {
lock.unlock();
}
}
Future<void> updateUser(Map<String, dynamic> user, int id) async {
await lock.lock();
try {
final db = await instance.database;
await db.transaction((txn) async {
await txn.update(
'users',
user,
where: 'id =?',
whereArgs: [id],
);
});
} finally {
lock.unlock();
}
}
Future<void> deleteUser(int id) async {
await lock.lock();
try {
final db = await instance.database;
await db.transaction((txn) async {
await txn.delete(
'users',
where: 'id =?',
whereArgs: [id],
);
});
} finally {
lock.unlock();
}
}
Future<List<Map<String, dynamic>>> queryAllUsers() async {
await lock.lock();
try {
final db = await instance.database;
return await db.query('users');
} finally {
lock.unlock();
}
}
}
在上述代码中:
DatabaseHelper
类负责管理数据库连接和操作。lock
实例用于同步并发操作。insertUser
、updateUser
、deleteUser
和queryAllUsers
方法展示了如何在获取锁后进行数据库事务操作,确保数据的一致性和完整性,同时处理并发冲突。