公司法人查询系统,seo推广哪家好,做旅游网站,开通微网站Flutter笔记 用于ORM的Floor框架简记 本文地址#xff1a;https://blog.csdn.net/qq_28550263/article/details/133377191
floor 模块地址#xff1a;https://pub.dev/packages/floor 【介绍】#xff1a;最近想找用于Dart和Flutter的ORM框架#xff0c;偶然间发现了Floor… Flutter笔记 用于ORM的Floor框架简记 本文地址https://blog.csdn.net/qq_28550263/article/details/133377191
floor 模块地址https://pub.dev/packages/floor 【介绍】最近想找用于Dart和Flutter的ORM框架偶然间发现了Floor觉得还不错做一些记录。 1. Floor 框架概述1.1 框架简介1.2 框架的构成1.3 安装1.4 架构体系2. 实体Entity支持的类型主键外键索引忽略字段继承 数据库视图Database Views 3. 数据访问对象DAO - Data Access Object4. 创建数据库5. 运行代码生成器6. 使用生成的代码 1. Floor 框架概述
1.1 框架简介
Floor 框架是一个用于在 Flutter 应用程序中使用 SQLite 数据库的开源库。它允许开发者轻松地将本地数据库集成到其应用程序中并提供了一种类型安全、高效和易于使用的方法来执行数据库操作。
1.2 框架的构成
Floor 框架由多个关键模块组成每个模块都有特定的功能协同工作以实现在 Flutter 应用程序中使用 SQLite 数据库的目标。以下是 Floor 框架的主要模块以及它们的作用 floor运行时库 作用 floor 是 Floor 框架的运行时库包含用于运行时数据库操作的类和方法。关键类和方法FloorDatabase抽象类表示数据库的根类生成的数据库类需要扩展它。Database用于标记生成的数据库类指定数据库版本号、实体列表和其他配置信息。databaseBuilder用于创建数据库实例的方法。数据库操作方法生成的数据库类中包含与数据库表的交互方法例如插入、查询、更新等。 floor_generator代码生成器 作用 floor_generator 是 Floor 框架的代码生成器模块它会根据实体和 DAO 的定义生成数据库访问代码。生成的代码 该模块生成包括数据库类、DAO 类以及其他与数据库交互相关的代码使开发者能够轻松执行数据库操作而无需手动编写大量的重复代码。 floor_annotationFloor 框架中的注解 作用 floor_annotation是Floor 框架中的注解。这些注解用于标记和配置数据库实体Entities、数据访问对象DAOs以及数据库操作以便 Floor 框架的代码生成器 floor_generator 可以根据这些注解生成相应的数据库访问代码。floor_annotation 提供了一种类型安全的方式来配置和定义数据库操作并允许开发者在 Dart 代码中使用注解来描述数据库模型和操作而无需手动编写大量的重复代码。例如 entity用于标记 Dart 类表示它是一个数据库实体Entity。实体类通常与数据库表相对应用于定义表的结构和字段。dao用于标记抽象类或接口表示它是数据访问对象DAO。DAO 类包含了与数据库表相关的操作方法如插入、查询、更新和删除。
等等
sqflite数据库驱动由floor自动调用 作用 Floor 框架依赖于 sqflite 插件它提供了在 Flutter 中与 SQLite 数据库进行底层交互的功能。sqflite 插件负责管理 SQLite 数据库文件、执行原始 SQL 查询和处理数据库事务。
这些模块协同工作使开发者能够轻松地在 Flutter 应用程序中集成和操作 SQLite 数据库。通过定义实体、DAO 和数据库然后运行代码生成器开发者可以获得类型安全、高效和易于维护的数据库访问代码从而实现数据持久化和本地数据存储的需求。
build_runnerbuild_runner 通常与 floor_generator 一起使用以自动生成与数据库操作相关的 Dart 代码。
1.3 安装
flutter pub add floor
flutter pub add floor_generator build_runner --dev其中
floor 包含了将在应用程序中使用的所有代码。floor_generator 包含了生成数据库类的代码。build_runner 允许以具体的方式生成源代码文件。
将在你的yaml中看到
dependencies:flutter:sdk: flutterfloor: ^1.4.0dev_dependencies:floor_generator: ^1.4.0build_runner: ^2.1.2版本可能随时间变化
1.4 架构体系
存储和访问数据的组件是 实体、数据访问对象(DAO) 和 数据库
一个 实体 代表一个 持久类也就是一个 数据库表Dao管理对实体的访问并负责内存中 对象 和表行 之间的 映射数据库是底层 SQLite 数据库的中心访问点。它 保存Dao除此之外还负责 初始化数据库及其 模式。 2. 实体Entity
一个实体是一个持久化类。Floor 自动创建内存中对象与数据库表行之间的映射。可以通过向 Entity 注释添加可选值来向 Floor 提供自定义元数据。它具有表名 tableName 的附加属性该属性打开了为特定实体使用自定义名称的可能性而不是使用类名。foreignKeys 允许向实体添加外键。有关如何使用这些内容的更多信息请参阅外键部分。还支持索引。可以通过将索引添加到实体的 indices 值来使用它们。
entity 注解用于标记了该类为持久类PrimaryKey 将类的属性标记为主键列。该属性必须是 int 类型。当启用 autoGenerate 时SQLite 可以自动生成该值必须通过将 primaryKey 注解添加到一个 int 属性上为你的表添加一个主键例如// entity/person.dartimport package: floor/floor.dart;entity
class Person {primaryKeyfinal int id;final String name;Person(this.id, this.name);
}ColumnInfo 使单个表列的自定义映射变得可能。使用该注释可以为列指定自定义名称。如果要将表的列设置为可空请将实体字段标记为可空Floor 自动使用实体类中定义的第一个构造函数来从数据库行创建内存中对象
支持的类型
Floor 实体可以保存以下 Dart 类型的值这些类型与它们对应的 SQLite 类型相互映射。
int - INTEGERdouble - REALString - TEXTbool - INTEGER0 false1 trueUint8List - BLOBenum - INTEGER按索引 0…n 记录
如果要存储可以由上述类型之一表示的复杂 Dart 对象请查看类型转换器。
主键
每当需要复合主键例如 n-m 关系时设置主键的语法与前面提到的设置主键的方式不同。不是使用 PrimaryKey 注释字段而是使用 Entity 注释的 primaryKey 属性。它接受一个由列名组成的列表这些列名组成复合主键。
Entity(primaryKeys: [id, name])
class Person {final int id;final String name;Person(this.id, this.name);
}外键
向引用实体的 Entity 注释添加 ForeignKeys 列表。childColumns 定义当前实体的列而 parentColumns 定义父实体的列。在 onUpdate 和 onDelete 属性中定义外键操作后可以触发外键操作。
// Dog 类表示数据库中的狗实体
Entity(tableName: dog, // 指定表名为 dogforeignKeys: [ForeignKey(childColumns: [owner_id], // 子列名为 owner_idparentColumns: [id], // 父列名为 identity: Person, // 引用的实体为 Person 类)],
)
class Dog {PrimaryKey() // PrimaryKey 注解将 id 标记为主键列final int id;final String name; // 名称ColumnInfo(name: owner_id) // ColumnInfo 注解自定义列名为 owner_idfinal int ownerId; // 所有者的 ID// 构造函数接受 id、name 和 ownerId 参数Dog(this.id, this.name, this.ownerId);
}Entity 注解标记了 Dog 类指定了表名为 ‘dog’同时指定了一个外键foreign key该外键将在 ‘owner_id’ 列上创建它引用了另一个实体 Person。这意味着在数据库中将创建名为 ‘dog’ 的表并在 ‘owner_id’ 列上创建一个外键以确保数据的完整性。PrimaryKey 注解标记了 id 字段作为主键列这意味着它在数据库中将用作主键。ColumnInfo 注解标记了 ownerId 字段并自定义了列名为 ‘owner_id’这允许在数据库表中使用不同的列名而不是默认的字段名。构造函数接受 id、name 和 ownerId 参数并用于创建 Dog 实例。
这些注释和注释说明了 Dog 类的结构以及如何配置表名、外键和自定义列名。
索引
索引有助于加速查询、连接和分组操作。有关 SQLite 索引的更多信息请参阅官方文档。要在 floor 中创建索引请将索引列表添加到 Entity 注释。下面的示例演示了如何在实体的 custom_name 列上创建索引。
此外可以使用其 name 属性命名索引。要将索引设置为唯一索引请使用 unique 属性。
// Person 类表示数据库中的个人实体
Entity(tableName: person, indices: [Index(value: [custom_name])])
class Person {primaryKey // PrimaryKey 注解将 id 标记为主键列final int id;ColumnInfo(name: custom_name) // ColumnInfo 注解自定义列名为 custom_namefinal String name; // 姓名// 构造函数接受 id 和 name 参数Person(this.id, this.name);
}Entity 注解标记了 Person 类指定了表名为 ‘person’同时指定了一个索引该索引将在 ‘custom_name’ 列上创建。这意味着在数据库中将创建名为 ‘person’ 的表并在 ‘custom_name’ 列上创建一个索引以提高查询性能。primaryKey 注解标记了 id 字段作为主键列这意味着它在数据库中将用作主键。ColumnInfo 注解标记了 name 字段并自定义了列名为 ‘custom_name’这允许在数据库表中使用不同的列名而不是默认的字段名。 构造函数接受 id 和 name 参数并用于创建 Person 实例。
忽略字段
默认情况下实体的 getter、setter 和所有静态字段都会被忽略并因此从库的映射中排除。如果要进一步忽略字段应使用 ignore 注释并按以下示例中所示应用它。
// 人员类表示数据库中的人员实体
class Person {primaryKey // PrimaryKey 注解将 id 标记为主键列final int id;final String name; // 姓名ignore // Ignore 注解指定 nickname 字段将被忽略String nickname; // 昵称// 默认情况下被忽略的字段不会包含在库的映射中String get combinedName $name ($nickname);// 构造函数接受 id 和 name 参数Person(this.id, this.name);
}
继承
与 Dao 一样实体和数据库视图可以从共同的基类继承并使用它们的字段。实体只需扩展基类。这个构造将被视为如果基类的所有字段都是实体的一部分这意味着数据库表将包含实体和基类的所有列。
基类不必为类单独注释。它的字段可以像正常的实体列一样进行注释。外键和索引必须在实体中声明不能在基类中定义。
// 基础对象类用于继承到其他实体
class BaseObject {// 主键标记指定 id 作为主键列PrimaryKey()final int id;// ColumnInfo 注解用于自定义列名 create_timeColumnInfo(name: create_time)final String createTime;// ColumnInfo 注解用于自定义列名 update_timeColumnInfo(name: update_time)final String updateTime;// 构造函数接受 id、updateTime 和可选的 createTime 参数BaseObject(this.id,this.updateTime, {String createTime,}) : this.createTime createTime ?? DateTime.now().toString();// 重写父类的 props 方法通常用于数据比较overrideListObject get props [];
}// Comment 类继承自 BaseObject 类
Entity(tableName: comments) // Entity 注解指定表名为 comments
class Comment extends BaseObject {final String author; // 评论作者final String content; // 评论内容// 构造函数接受 author、可选的 id、content、createTime 和 updateTime 参数Comment(this.author, {int id,this.content , // 默认为空字符串String createTime,String updateTime,}) : super(id, updateTime, createTime: createTime); // 调用父类构造函数传递 id、updateTime 和 createTime 参数
}
数据库视图Database Views
如果希望定义返回与实体不同类型的静态 SELECT 语句最佳选择是使用 DatabaseView。数据库视图可以被理解为虚拟表可以像真实表一样进行查询。
在 Floor 中数据库视图的定义和使用方式与实体类似主要区别在于只读访问这意味着无法执行更新、插入和删除操作。与实体类似如果未设置 viewName则使用类名。
DatabaseView(SELECT distinct(name) AS name FROM person, viewName: name)
class Name {final String name;Name(this.name);
}数据库视图不具有任何外键、主键或索引。相反您应该手动定义与您的语句匹配的索引并将它们放入涉及实体的 Entity 注释中。
与实体类似setter、getter 和静态字段将自动被忽略与实体类似您可以使用 ignore 注解来指定要忽略的附加字段。
在代码中定义数据库视图后您需要将它添加到 Database 注释的 views 字段中
Database(version: 1, entities: [Person], views: [Name])
abstract class AppDatabase extends FloorDatabase {// DAO 获取器
}然后您可以通过 DAO 函数查询视图就像查询实体一样。
数据库视图可以像实体一样从基类继承共同字段。 现在可以从 DAO 方法返回一个 Stream 对象该方法查询数据库视图。但是它将在整个数据库中的任何 update、insert、delete 事件触发时发出这可能会对运行时产生相当大的负担。请仅在明白自己在做什么时才添加它这主要是因为检测哪些实体涉及到数据库视图的复杂性所致。 3. 数据访问对象DAO - Data Access Object
这个组件负责管理对底层的 SQLite 数据库的访问。抽象类包含了查询数据库的方法签名这些方法必须返回 Future 或 Stream。
你可以通过将 Query 注解添加到方法上来定义查询。SQL 语句必须放在括号中。方法必须返回你查询的实体的 Future 或 Stream。 insert 标记了一个方法作为插入方法。
// dao/person_dao.dartimport package:floor/floor.dart;dao
abstract class PersonDao {// 查询并返回所有的 Person 实体对象列表Query(SELECT * FROM Person)FutureListPerson findAllPersons();// 根据提供的 id 查询并返回匹配的 Person 实体对象// 这是一个异步数据流当数据发生变化时会自动更新Query(SELECT * FROM Person WHERE id :id)StreamPerson? findPersonById(int id);// 将提供的 Person 对象插入到数据库中// 这是一个异步操作不返回任何数据insertFuturevoid insertPerson(Person person);
}
4. 创建数据库
它必须是一个继承自 FloorDatabase 的抽象类。此外必须在类的签名中添加 Database()。确保将创建的实体添加到 Database 注解的 entities 属性中。为了使生成的代码工作还需要添加列出的导入项。
确保在这个文件的导入项下面添加 part ‘database.g.dart’;。重要的是要注意 ‘database’ 必须与数据库定义的文件名进行交换。在这种情况下文件名命名为 database.dart。
// database.dartimport dart:async;
import package:floor/floor.dart;
import package:sqflite/sqflite.dart as sqflite; import dao/person_dao.dart;
import entity/person.dart; part database.g.dart; // Floor代码生成器将在这里生成相关的代码Database(version: 1, entities: [Person]) // 声明数据库版本号和包含的实体类
abstract class AppDatabase extends FloorDatabase {PersonDao get personDao; // 获取PersonDao实例用于执行数据库操作
}
5. 运行代码生成器
使用以下命令来运行生成器
flutter packages pub run build_runner build上面的命令用于在 Flutter 项目中运行代码生成工具以手动构建生成的代码。build命令 只会运行一次生成过程然后退出。还可以在 Flutter 项目中使用 build_runner 模块的观察模式以便在开发过程中自动更新生成的代码。如果想要在文件更改时自动运行它请使用以下命令
flutter packages pub run build_runner watch6. 使用生成的代码
要获取数据库的实例使用生成的 $FloorAppDatabase 类它允许访问数据库生成器。名称由 $Floor 和数据库类名组成。传递给 databaseBuilder() 的字符串将是数据库文件的名称。要初始化数据库调用 build() 并确保等待结果。
为了检索 PersonDao 实例只需在数据库实例上调用 persoDao getter 即可。 可以参考下面的代码。
// 使用数据库生成器创建数据库实例传递数据库文件的名称app_database.db
final database await $FloorAppDatabase.databaseBuilder(app_database.db).build();// 从数据库实例中获取 PersonDao 实例
final personDao database.personDao;// 创建一个 Person 对象
final person Person(1, Frank);// 将新的 Person 对象插入到数据库中
await personDao.insertPerson(person);// 通过 ID 查找数据库中的 Person 记录
final result await personDao.findPersonById(1);// 输出查找到的 Person 记录
print(Found Person: $result);