Flutter Sqflite多表模型

时间:2018-12-05 10:49:29

标签: sqlite dart flutter singleton

我已经阅读了许多有关如何在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;
}

2 个答案:

答案 0 :(得分:0)

我提出了一些意见,建议与此相反,但是我只记得在我的上一个项目中我做了类似的事情,它用于 Firebase数据库,但是对于 sqflite < / strong>。

我用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方法最终在每个特定于模型的提供程序中都必须有所不同。但是,可以简化很多事情。

我在评论中说的是,这最后一类,即具有NewsProvidertoJson特定实现的特定fromMap,也可以通过在{{ 1}}模型类,但这带来了很多问题和模糊性,而且-我个人认为 -不值得。

答案 1 :(得分:0)

我对创建表有一个类似的问题,所有示例仅创建一个表。我发现这个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)");
    }