Flutter Moor 如何获取nullsafe类型的GeneratedColumn?
问题描述
无论GeneratedColumn的定义中是否配置nullable(),其泛型数据类型始终为可空类型,即便使用TextColumn或Column<String>(及其他同类型定义)也无差异,示例如下:
示例代码
手写的db.dart定义
import 'package:moor/moor.dart'; part 'db.g.dart'; class FooTable extends Table { Column<String> get id => text()(); Column<int> get someNumber => integer()(); Column<DateTime> get someDate => dateTime()(); } @UseMoor(tables: <Type>[FooTable]) class Db extends _$Db { // ... }
自动生成的db.g.dart对应实现
class $FooTableTable extends FooTable with TableInfo<$FooTableTable, FooTableData> { final GeneratedDatabase _db; final String? _alias; $FooTableTable(this._db, [this._alias]); final VerificationMeta _idMeta = const VerificationMeta('id'); late final GeneratedColumn<String?> id = GeneratedColumn<String?>( 'id', aliasedName, false, typeName: 'TEXT', requiredDuringInsert: true); final VerificationMeta _someNumberMeta = const VerificationMeta('someNumber'); late final GeneratedColumn<int?> someNumber = GeneratedColumn<int?>( 'some_number', aliasedName, false, typeName: 'INTEGER', requiredDuringInsert: true); final VerificationMeta _someDateMeta = const VerificationMeta('someDate'); late final GeneratedColumn<DateTime?> someDate = GeneratedColumn<DateTime?>( 'some_date', aliasedName, false, typeName: 'INTEGER', requiredDuringInsert: true); @override List<GeneratedColumn> get $columns => [id, someNumber, someDate]; @override String get aliasedName => _alias ?? 'foo_table'; @override String get actualTableName => 'foo_table'; @override VerificationContext validateIntegrity(Insertable<FooTableData> instance, {bool isInserting = false}) { final context = VerificationContext(); final data = instance.toColumns(true); if (data.containsKey('id')) { context.handle(_idMeta, id.isAcceptableOrUnknown(data['id']!, _idMeta)); } else if (isInserting) { context.missing(_idMeta); } if (data.containsKey('some_number')) { context.handle( _someNumberMeta, someNumber.isAcceptableOrUnknown( data['some_number']!, _someNumberMeta)); } else if (isInserting) { context.missing(_someNumberMeta); } if (data.containsKey('some_date')) { context.handle(_someDateMeta, someDate.isAcceptableOrUnknown(data['some_date']!, _someDateMeta)); } else if (isInserting) { context.missing(_someDateMeta); } return context; } @override Set<GeneratedColumn> get $primaryKey => <GeneratedColumn>{}; @override FooTableData map(Map<String, dynamic> data, {String? tablePrefix}) { return FooTableData.fromData(data, _db, prefix: tablePrefix != null ? '$tablePrefix.' : null); } @override $FooTableTable createAlias(String alias) { return $FooTableTable(_db, alias); } }
核心疑问
项目中的列定义为Column<String> get id => text()(),但自动生成的列类型为GeneratedColumn<String?> id,是否有方法获取GeneratedColumn<String>(即null safety非空类型)的生成列?
解答
不存在生成非空泛型GeneratedColumn的配置方式,这是框架的刻意设计:
GeneratedColumn统一使用可空泛型,是为了覆盖所有SQL查询场景的返回可能:哪怕列在表结构中定义为非空,执行左连接、外连接、聚合查询时,该列的返回值依然可能为null,只有可空泛型能完全适配这类场景,避免空安全运行时错误。- 表定义中声明的
Column<String>、integer()这类非空列标记,仅作用于两个核心流程:一是插入、更新数据时的完整性校验,框架会强制要求传入对应非空值;二是自动生成的表实体类(比如示例中的FooTableData)中,对应字段会被标记为非空类型,常规单表查询拿到实体后读取字段不需要额外判空。 - 不要手动修改生成文件把泛型改成非空,否则连接查询场景下大概率触发空指针异常。日常编写查询逻辑时直接用框架内置的表达式、
Value封装类操作列即可,不需要额外处理列本身的泛型类型。
内容的提问来源于stack exchange,提问作者Stacky
相关产品推荐
相关产品推荐

