Amplify DataStore关联模型无法同步远程但本地查询正常的排查求助
问题描述
使用Amplify DataStore时遇到异常:保存关联User的Goal模型时,数据仅能在本地查询到,无法同步至远程数据库;但移除goalOfUser字段时可正常保存到远程(需保留该字段建立双向关联)。执行查询函数能返回保存的数据,但数据的createdAt字段为null。需调试Amplify.DataStore.save()函数定位问题,或指出配置/代码错误。
相关代码
Schema定义
type User @model @auth(rules: [{allow: public}]) { id: ID! userEmail: AWSEmail! userName: String! userPassword: String! userGoals: [Goal] @hasMany(indexName: "byUser", fields: ["id"]) } type Goal @model @auth(rules: [{allow: public}]) { id: ID! goalStart: AWSDateTime! goalEnd: AWSDateTime goalCategory: CategoryTypes! goalCurrentDuration: DurationBeat! goalTargetDuration: DurationBeat! goalPercentage: Float userID: ID! @index(name: "byUser") goalActivities: [Activity] @hasMany(indexName: "byGoal", fields: ["id"]) goalOfUser: User! @belongsTo }
保存Goal的代码
Future<void> createGoal(String userID, CategoryTypes category, DurationBeat targetDuration) async { final Goal goal = Goal( userID: userID, goalCategory: category, goalTargetDuration: targetDuration, goalCurrentDuration: DurationBeat( durationHours: 0, durationMinutes: 0, durationSeconds: 0), goalPercentage: 0, goalStart: _today, //Local datetime variable goalEnd: null, //Null when the goal is current. Date assigned when the user sets new goal. goalOfUser: global.currentUser //Globally accessible user instance ); await Amplify.DataStore.save(goal); }
查询代码
Future<Goal> getLatestGoal(CategoryTypes category, String userId) async { final record = await Amplify.DataStore.query(Goal.classType, where: Goal.USERID .eq(userId) .and(Goal.GOALCATEGORY.eq(category)) .and(Goal.GOALEND.eq(null)), sortBy: [Goal.GOALEND.ascending()]); return record.first; }
返回的数据示例
Goal {id=710ddbeb-89b5-4bcd-9623-8232b4e8a545, goalStart=2022-07-23T04:00:00.000000000Z, goalEnd=null, goalCategory=FITNESS, goalCurrentDuration=DurationBeat {durationSeconds=0, durationMinutes=0, durationHours=0}, goalTargetDuration=DurationBeat {durationSeconds=0, durationMinutes=5, durationHours=1}, goalPercentage=0.0, userID=190c7bd1-02ad-4ab1-970d-49b8e6f7a9f8, goalOfUser=User {id=190c7bd1-02ad-4ab1-970d-49b8e6f7a9f8, userEmail=charlesrichardsonusa@gmail.com, userName=Charbo, userPassword=password, createdAt=2022-07-19T20:23:09.797000000Z, updatedAt=2022-07-23T05:06:18.321000000Z}, createdAt=null, updatedAt=null}
解决方案
一、修复Schema关联配置
@belongsTo字段未指定关联外键,Amplify无法正确映射双向关联。修改Goal模型的goalOfUser字段:
goalOfUser: User! @belongsTo(fields: ["userID"])
明确指定该关联依赖userID字段,确保关联关系映射正确。
二、修正保存代码的关联赋值
保存Goal时不要传入完整User实例,仅需传入User的ID标识,避免循环引用或数据不一致:
final Goal goal = Goal( userID: userID, goalCategory: category, goalTargetDuration: targetDuration, goalCurrentDuration: DurationBeat( durationHours: 0, durationMinutes: 0, durationSeconds: 0), goalPercentage: 0, goalStart: _today, goalEnd: null, // 仅传入User的id,而非完整实例 goalOfUser: User(id: userID) );
三、调试DataStore同步问题的方法
- 开启详细日志:初始化Amplify时开启verbose日志,查看同步过程中的错误:
Amplify.addPlugin(AmplifyDataStore(modelProvider: ModelProvider.instance)); await Amplify.configure(amplifyconfig); Amplify.Logging.logLevel = LogLevel.verbose; // 监听DataStore事件 Amplify.DataStore.observe().listen((event) { print('DataStore事件: ${event.eventType} - ${event.item}'); });
通过日志排查同步失败的具体原因(如权限错误、字段验证失败等)。
- 查询待同步数据:查看本地是否有未同步的Pending数据:
final pendingGoals = await Amplify.DataStore.query( Goal.classType, syncStatus: SyncStatus.PENDING ); print('待同步Goal数量: ${pendingGoals.length}');
- 手动触发同步:调用手动同步函数,观察是否抛出异常:
try { await Amplify.DataStore.sync(); print('同步完成'); } catch (e) { print('同步失败: $e'); }
- 验证远程权限:确认AppSync的API密钥或认证配置正确,确保public权限允许创建关联数据。
四、关于createdAt为null的说明
createdAt和updatedAt由Amplify远程数据库自动生成,本地数据未同步时该字段为null。解决同步问题后,数据同步到远程会自动填充这两个字段。
内容的提问来源于stack exchange,提问作者C RICH
相关产品推荐
相关产品推荐

