验证 Drift 数据是否成功存入 SQLite 的几种方案
前提:你的
MessageRecords表已经加上主键,代码已经改好。分代码内验证 、外部工具查看数据库文件两种方式。
✅ 方式 1:代码内验证(推荐,单元测试 / 业务校验)
方案 A:upsert 之后立刻查询(你已有 findMessageById)
dart
// 写入
await messageDao.upsertMessage(message);
// 立刻查询
final savedMsg = await messageDao.findMessageById(message.id);
if(savedMsg != null){
print("✅ 数据真实落库");
}else{
print("❌ 数据库找不到这条记录");
}
方案 B:单元测试(flutter test)
ini
test('upsert message should save to db', () async {
final msg = Message(id: "msg_001", content: "hello", timestamp: DateTime.now(), isUser: true);
await dao.upsertMessage(msg);
final find = await dao.findMessageById("msg_001");
expect(find?.content, "hello");
});
✅ 方式 2:找到 SQLite 文件,用数据库工具直接打开查看(最直观)
你的 drift 配置:
less
driftDatabase(
name: 'my_database',
native: const DriftNativeOptions(
databaseDirectory: getApplicationSupportDirectory,
),
);
数据库文件名:my_database.sqlite
不同平台数据库文件位置
- Android(模拟器 / 真机)
/data/data/[你的应用包名]/files/my_database.sqlite
真机需要 root;模拟器可以用 Android Studio Device File Explorer 导出文件。
- iOS 模拟器
bash
~/Library/Developer/CoreSimulator/Devices/[uuid]/data/Containers/Data/Application/[app-uuid]/Library/Application Support/my_database.sqlite
- macOS 桌面端
~/Library/Application Support/[你的app包名]/my_database.sqlite - Windows
%APPDATA%/[你的app名称]/my_database.sqlite
查看工具推荐
- DB Browser for SQLite (免费,跨平台,首选)sqlitebrowser.org/
- DBeaver
- VSCode 插件:SQLite Viewer
操作步骤:
- 导出
my_database.sqlite - 用 DB Browser 打开
- 打开
message_records表,查看里面的记录
表名:drift 默认会把 Dart 类名
MessageRecords转成 snake_casemessage_records
✅ 方式 3:Drift 开启 SQL 日志,看底层执行语句
可以在创建数据库的时候开启日志,打印所有 SQL 语句,确认 SQL 有没有正常执行:
css
MessageDatabase([QueryExecutor? executor])
: super(
executor ?? _openConnection(),
// 开启日志
logStatements: true,
);
开启后控制台会打印:
sql
INSERT INTO message_records (id, content, timestamp, is_user) VALUES (?, ?, ?, ?) ON CONFLICT(id) DO UPDATE SET ...
看到这条日志代表 drift 已经下发 SQL 到 sqlite。
⚠️ 注意:SQL 打印只代表语句下发,不等于写入成功,最终还是要查询数据库确认。
✅ 方式 4:直接写原生 SQL 查询(Drift 支持)
dart
final result = await database.customSelect(
'SELECT * FROM message_records WHERE id = ?',
variables: [Variable<String>("msg_001")],
).getSingleOrNull();
if(result != null){
print("✅ 原生SQL查到数据: ${result.data}");
}else{
print("❌ 无数据");
}
常见踩坑点
- 热重载不会重建数据库:修改表结构后,必须卸载 App / 删除应用数据,否则旧表结构还在。
insertOnConflictUpdate必须有主键primaryKey => {id},否则不会触发更新,会重复插入。- 模拟器和真机数据库文件是分开的,不要搞混。
logStatements:true只适合开发环境,上线记得关闭。
快速推荐组合
开发调试:开启 logStatements + DB Browser 导出 sqlite 文件看表 业务代码校验:upsert 完成后调用 findMessageById 二次校验
iOS 模拟器验证 Drift(3 种方法,推荐顺序:打印路径 → xcrun 命令 → Xcode 下载容器)
你的 drift 配置:
databaseDirectory: getApplicationSupportDirectory文件:my_database.sqlite,配套还有my_database.sqlite-wal、my_database.sqlite-shm(WAL 日志,三个文件放一起才能正常打开 ) 表名:message_records
✅ 方法 1:代码打印数据库路径(最简单,优先用)
直接在 Flutter 里输出数据库完整路径,复制到 mac 访达打开。 修改 MessageDatabase,增加打印路径:
dart
import 'package:path_provider/path_provider.dart';
// 在初始化或者调试按钮里执行
Future<void> printDbPath() async {
final dir = await getApplicationSupportDirectory();
final dbPath = "${dir.path}/my_database.sqlite";
logger.i("📦 iOS模拟器DB路径:$dbPath");
}
运行 App,模拟器执行一次,控制台拿到路径,复制到 mac 访达:
- 打开访达,按
Shift+Cmd+G - 粘贴路径,回车,直接跳转到文件夹
- 把
my_database.sqlite、wal、shm 三个文件复制到别的文件夹备份 - 使用 DB Browser for SQLite 打开
my_database.sqlite,查看message_records表里的数据
⚠️ 注意:模拟器 App 运行时,不要直接打开原文件,会被 sqlite WAL 锁,建议复制出来再打开。
✅ 方法 2:终端 xcrun 命令(mac 终端,不用改代码)
前提:模拟器已经启动、App 在模拟器安装 ,替换 com.xxx.yourapp 为你的 iOS bundle id(在 ios/Runner/Info.plist 里面找)
kotlin
# 获取模拟器App的data目录
xcrun simctl get_app_container booted com.xxx.yourapp data
执行后会输出目录,进入 Library/Application Support/,里面就是 my_database.sqlite。
一键 cd 到数据库目录示例:
bash
cd "$(xcrun simctl get_app_container booted com.xxx.yourapp data)/Library/Application Support"
ls
看到 my_database.sqlite 就是成功。
✅ 方法 3:Xcode 下载 App 容器(图形化,适合新手)
- 打开 Xcode → 顶部菜单
Window→Devices and Simulators - 切换到 Simulators 标签,选中你正在跑的模拟器
- 在右边 Installed Apps 列表找到你的 App
- 点下方齿轮图标 → Download Container
- 等待下载完成,得到
.xcappdata文件 - 右键这个文件 → Show Package Contents
- 进入
AppData/Library/Application Support/,就能拿到 sqlite 文件 - 复制出来,DB Browser 打开查看
message_records
✅ 方法 4:代码内校验(不用导出文件,业务验证)
dart
// upsert写入之后立刻查询
await messageDao.upsertMessage(msg);
final result = await messageDao.findMessageById(msg.id);
if(result != null){
print("✅ 数据库已持久保存");
}else{
print("❌ 数据库没有写入");
}
✅ 方法 5:开启 Drift SQL 日志,看执行 SQL
css
MessageDatabase([QueryExecutor? executor])
: super(executor ?? _openConnection(), logStatements: true);
控制台会打印完整 SQL 语句,确认 INSERT ... ON CONFLICT 语句下发成功。
日志只代表 SQL 下发,必须查询数据库才代表落库成功。
重要踩坑(iOS 模拟器高频)
- 切换模拟器 = 全新数据库,iPhone15 模拟器 和 iPhone16 模拟器 的数据库完全独立。
- 模拟器删除 App,数据库全部清空。
- WAL 模式:
.sqlite-wal是预写日志,打开数据库必须连同 wal、shm 一起复制,只拷贝 sqlite 主文件会看不到新写入的数据! - 修改表结构(新增主键)后,模拟器里必须卸载 App 重装,旧数据库不会自动更新表结构。
DB Browser for SQLite 操作
- 打开 DB Browser → Open Database → 选中复制出来的
my_database.sqlite - 切换到
Browse Data,表选择message_records,直接看所有消息记录。