Flutter中使用Drift时如何实现数据库与模型的映射?
最佳数据映射方案(Drift + SQLite)
针对你提到的「避免手动重复映射、Model与数据库解耦」的需求,以下是几种实用的解决方案,按推荐优先级排序:
1. 专用映射器类(最推荐,解耦彻底)
创建独立的映射器类,专门负责DataClass(Drift生成)与ModelClass(自定义业务模型)之间的转换逻辑。这种方式完全隔离了业务模型与数据库实现,符合单一职责原则,也便于集中维护映射规则。
示例代码:
// 映射器类:仅处理数据转换,不涉及业务或数据库操作 class TodoMapper { // 将Drift生成的DataClass转为业务Model static TodoModel toModel(TodoData data) { return TodoModel( id: data.id, title: data.title, isCompleted: data.isCompleted, dueDate: data.dueDate, ); } // 将业务Model转为Drift的DataClass static TodoData toData(TodoModel model) { return TodoData( id: model.id, title: model.title, isCompleted: model.isCompleted, dueDate: model.dueDate, ); } // 批量转换(避免重复写map逻辑) static List<TodoModel> toModelList(List<TodoData> dataList) { return dataList.map(toModel).toList(); } }
在Repository中使用:
class TodoRepository { final MyDatabase _db; TodoRepository(this._db); Future<List<TodoModel>> getTodos() async { final dataList = await _db.select(_db.todos).get(); // 调用映射器批量转换 return TodoMapper.toModelList(dataList); } Future<void> addTodo(TodoModel model) async { final data = TodoMapper.toData(model); await _db.into(_db.todos).insert(data); } }
优点:业务Model完全无需知晓数据库细节,映射逻辑集中管理,修改或新增规则只需改动映射器,不易出错。
缺点:需要额外编写映射器类,但这是合理的分层开销。
2. 扩展方法(轻量简洁,适合小型项目)
给Drift生成的DataClass和自定义ModelClass添加扩展方法,实现快速转换。这种方式代码更简洁,且不会污染Model本身的代码。
示例代码:
// 给Drift的TodoData添加转Model的扩展 extension TodoDataExt on TodoData { TodoModel toModel() { return TodoModel( id: id, title: title, isCompleted: isCompleted, dueDate: dueDate, ); } } // 给自定义Model添加转DataClass的扩展 extension TodoModelExt on TodoModel { TodoData toData() { return TodoData( id: id, title: title, isCompleted: isCompleted, dueDate: dueDate, ); } }
Repository中使用:
Future<List<TodoModel>> getTodos() async { final dataList = await _db.select(_db.todos).get(); return dataList.map((data) => data.toModel()).toList(); }
优点:代码简洁,无需额外类,开发效率高。
缺点:扩展方法可能分散在多个文件中,大型项目维护起来不如集中式映射器方便。
3. TypeConverter(仅适合字段级转换,不推荐对象级映射)
Drift的TypeConverter设计初衷是处理单个字段的类型适配(比如将枚举转成数据库支持的int/String、DateTime转成时间戳等),而非整个对象的映射。如果强行用它来做DataClass到ModelClass的转换,会导致Model与Drift产生耦合,违背你「解耦」的需求,因此不推荐在这个场景使用。
内容的提问来源于stack exchange,提问作者Mike
相关产品推荐
相关产品推荐

