【问题标题】:Flutter Sqflite multiple table modelsFlutter Sqflite 多表模型
【发布时间】:2019-05-06 22:04:44
【问题描述】:

我已经阅读了许多关于如何在 Flutter 中实现 Sqflite 的教程和示例。其他所有示例仅使用一个模型或数据库表完成。如这些教程中所定义:

https://pub.dartlang.org/packages/sqflite

https://www.developerlibs.com/2018/07/flutter-sqlite-database-example.html

http://camposha.info/flutter/sqflite-insert-select-show

据我了解,我们需要创建与表一样多的模型和助手。对于每个数据库表,都会有一个 model.dart 文件和一个 helper.dart 文件。

我的问题是,有什么方法可以让所有模型都只有一个助手?

更新

在 helper.dart 文件中有一个未来的“插入”。如何为所有模型使用相同的插入未来?

Future<Todo> insert(Todo todo) async {
    todo.id = await db.insert(tableTodo, todo.toMap());
    return todo;
}

【问题讨论】:

  • openDatabase 中有onCreate 参数 - 使用它来创建任意数量的表 - 请参阅_onCreate here
  • 感谢@pskink,这很快。请查看我的问题,因为有更新。
  • 我不知道您所说的“所有型号的插入未来相同”的真正含义
  • 也许 OP 的意思是他想要定义模型,而框架会自动读取或保存这些模型/对象到 Sqflite 数据库中 - 也许是 Flutter Sqflite Hibernate 的一种?
  • 并以某种方式回答了这个问题,这可能使用元数据/注释,但我个人会逃避它。 :) 我很快搜索了一下,没有找到任何追求这个目标的包。

标签: sqlite dart flutter singleton


【解决方案1】:

我有一个关于创建表的类似问题,所有示例都只创建一个表。我发现这个webpage 创建了两个表,每个命令都等待。

像这样:

    Future _onCreate(Database db, int version) async {
        await db.execute("CREATE TABLE table1 (id INTEGER, valuex TEXT)");
        await db.execute("CREATE TABLE table2 (id INTEGER, valuey TEXT)");
        await db.execute("CREATE TABLE table3 (id INTEGER, valuez TEXT)");
    }

【讨论】:

    【解决方案2】:

    我做了一些相反的建议,但我只记得在我的上一个项目中我做了类似的事情,它是为 Firebase 数据库,但对于 sqflite。

    我创建了一个BaseItem 抽象类,带有一个key,所有模型都将从那个类继承。

    我还创建了一个 BaseProvider 抽象类,它需要一个 BaseItem 并定义访问模型的简单方法。

    upsertdelete 方法位于 FirebaseBaseProvider 中,它扩展了 BaseProvider

    我将在此处粘贴部分内容(删除了很​​多内容以使其更易于理解):

    abstract class BaseItem {
      const BaseItem({this.key});
      final String key;
    }
    
    abstract class BaseProvider<T extends BaseItem> {
      Future<List<T>> find();
    
      Future<BaseKey> upsert(T item);
    
      Future<int> delete(T item);
    }
    
    
    abstract class FirebaseBaseProvider<T extends BaseItem> {
      // Abstract methods which need to be implemented
      T fromMap(BaseKey key, dynamic map);
      Map<String, dynamic> toJson(BaseKey key, T item);
    
      Future<DatabaseReference> getReference(BaseKey base) async { ... }    
      BaseKey compileKey(T item, {String useKey}) { ... }
    
      Future<List<T>> find() async {
        List<T> result = new List();
        // my implementation doesnt work like this, 
        // as it's firebase based, but this would
        // be the place in a Sqflite implementation to use
        // fromMap and load the items
        return result;
      }
    
      Future<BaseKey> upsert(T item) async {
        if (item == null) return null;
    
        BaseKey key = compileKey(item);
        (await getReference(key)).set(toJson(key, item));
        return key;
      }
    
      Future<int> delete(T item) async {
        if (item == null) return null;
    
        if (item.key != null && item.key != "") {
          (await getReference(compileKey(item))).remove();
        }
        return 0;
      }
    }
    

    然后,为了实现 News 模型或任何其他模型,我将通过简单地定义其内容来创建它,如下所示:

    class News extends BaseItem {
      News({String key, this.creation, this.messageSubject, this.messageBody}) : super(key: key);
    
      final DateTime creation;
      final String messageSubject;
      final String messageBody;
    
      bool operator ==(o) => o is News && (o.key == key);
      int get hashCode => key.hashCode;
    }
    

    它需要特定的提供者,它只实现 toJsonfromMap 方法,就像这样:

    class NewsProvider extends FirebaseBaseProvider<News> {
      @override
      Map<String, dynamic> toJson(BaseKey key, News news) {
        return {
          "creation": news.creation,
          "messageSubject": news.messageSubject,
          "messageBody": news.messageBody,
        };
      }
    
      @override
      News fromMap(BaseKey key, dynamic map) {
        DateTime creation = map["creation"] == null ? null : DateTime.tryParse(map["creation"] as String);
    
        return new News(
          key: key.child.key,
          creation: creation,
          messageSubject: map["messageSubject"] as String,
          messageBody: map["messageBody"] as String,
        );
      }
    }
    

    最后,NewProvider 提供了findupsertdelete 方法,但它们的实现基于抽象类,如您所愿,仅适用于所有模型的一种实现。

    当然,我的实现要复杂得多,因为 Firebase 需要不同的方法来获取/加载项目,而且 find 方法最终必须在每个模型特定的提供者中有所不同。但是,很多东西都可以简化。

    我在评论中说的是最后一个类,即具有 toJsonfromMap 特定实现的特定 NewsProvider 也可以通过在 News 模型类中使用注释来概括,但是带来了很多问题和晦涩难懂 - 在我看来,当然 - 这不值得。

    【讨论】:

      猜你喜欢
      • 2021-12-26
      • 2019-10-21
      • 2019-08-16
      • 1970-01-01
      • 2021-11-22
      • 1970-01-01
      • 2020-10-16
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多