Flutter使用Floor库时出现List<>类型列不支持错误如何解决
问题原因
- SQLite本身不支持集合类型作为列存储,Floor没有办法直接把
List<Present>映射成SQLite支持的字段类型,这是你看到Column type is not supported for List<Present>报错的直接原因 - 你当前的外键配置逻辑完全错误:一对多关系(一个Person对应多个Present)的外键应该设置在子实体侧,也就是Present要持有Person的主键作为外键,而不是在父实体Person里存子实体的集合。
修复方案
1. 修正实体定义和外键配置
首先调整两个实体的代码,将外键放到Present实体中:
@Entity(tableName: 'Person') class Person { @PrimaryKey(autoGenerate: true) int? id; String name; Person({ this.id, required this.name, }); }
@Entity( tableName: 'Present', foreignKeys: [ ForeignKey( // 子表Present的关联字段 childColumns: ['personId'], // 父表Person的关联主键 parentColumns: ['id'], entity: Person, // 可选:Person删除时对应礼物也删除 onDelete: ForeignKeyAction.cascade, ) ], ) class Present { @PrimaryKey(autoGenerate: true) int? id; String name; double? price; // 关联Person的主键 int personId; Present({this.id, required this.name, this.price, required this.personId}); }
2. 定义关联查询的数据类
你需要额外定义一个非实体的POJO类用来封装带礼物列表的Person数据:
class PersonWithPresents { Person person; List<Present> presents; PersonWithPresents({required this.person, required this.presents}); }
3. 编写关联查询的DAO方法
在DAO中添加带事务的关联查询方法,Floor会自动处理结果映射:
@dao abstract class PersonDao { @Query('SELECT * FROM Person') Future<List<Person>> getAllPersons(); @Query('SELECT * FROM Present WHERE personId = :personId') Future<List<Present>> getPresentsByPersonId(int personId); @Transaction Future<List<PersonWithPresents>> getAllPersonsWithPresents() async { final persons = await getAllPersons(); final result = <PersonWithPresents>[]; for (final person in persons) { final presents = await getPresentsByPersonId(person.id!); result.add(PersonWithPresents(person: person, presents: presents)); } return result; } }
可选方案:使用TypeConverter直接序列化列表
如果你不需要对Present做独立的查询、也不需要外键约束,也可以通过TypeConverter把List<Present>序列化为JSON字符串存为TEXT类型,但这种方式不推荐用于需要关联查询的场景:
- 先给Present类添加
toJson和fromJson方法,可通过json_serializable自动生成 - 定义Converter
class PresentListConverter extends TypeConverter<List<Present>, String> { @override List<Present> decode(String databaseValue) { final list = jsonDecode(databaseValue) as List; return list.map((e) => Present.fromJson(e)).toList(); } @override String encode(List<Present> value) { return jsonEncode(value.map((e) => e.toJson()).toList()); } }
- 在Person实体上添加注解启用Converter,同时去掉外键配置即可
内容的提问来源于stack exchange,提问作者Andreas
相关产品推荐
相关产品推荐

