RestKit 多对多关系在连接表中保存新行,在主表中保存空值

Posted

技术标签:

【中文标题】RestKit 多对多关系在连接表中保存新行,在主表中保存空值【英文标题】:RestKit many to many relationship saves new rows in both join table and null values in main table 【发布时间】:2012-06-27 13:39:00 【问题描述】:

我使用 RestKit 在本地缓存来自远程服务器的数据。在其中,我在类别 > 新闻之间有多对多的关系。映射似乎工作正常,尽管它还在我的类别表中保存了空值(它也保存了正确的类别)。如下图:

似乎保存了 30 个空行,我的连接表中也有 30 个(非空)行,因此这里可能存在相关性。

我得到的 JSON 如下所示:"categories":["category_id":1,"category_id":4]

我有两个继承自 NSManagedObject 的自定义模型对象。

@interface News : NSManagedObject
    [...]
    @property (nonatomic, retain) NSSet *categories;
@end

@interface Category : NSManagedObject
[...]
    @property (nonatomic, retain) NSSet *news;
@end

我在两者上都使用@dynamic

我的映射如下所示:

RKManagedObjectMapping *categoryMapping = [RKManagedObjectMapping mappingForClass:[Category class] inManagedObjectStore:objectManager.objectStore];

categoryMapping.primaryKeyAttribute = @"categoryId";
categoryMapping.rootKeyPath = @"categories";
[categoryMapping mapKeyPath:@"id" toAttribute:@"categoryId"];
[...]

RKManagedObjectMapping* newsMapping = [RKManagedObjectMapping mappingForClass:[News class] inManagedObjectStore:objectManager.objectStore];

newsMapping.primaryKeyAttribute = @"newsId";
newsMapping.rootKeyPath = @"news";
[newsMapping mapKeyPath:@"id" toAttribute:@"newsId"];
[...]

// Categories many-to-many (not fully working yet).
[newsMapping mapKeyPath:@"categories" toRelationship:@"categories" withMapping: categoryMapping];

// Register the mappings with the provider
[objectManager.mappingProvider setObjectMapping:newsMapping forResourcePathPattern:@"[path-to-JSON]"];
[objectManager.mappingProvider setObjectMapping:categoryMapping forResourcePathPattern:@"[path-to-JSON]"];

我像这样获取数据(很像 Twitter RestKit 示例):

- (id)init

    self = [super init];
    if (self) 
        [self loadCategories];
        [self loadCategoriesFromDataStore];

        [self loadNews];
        [self loadNewsFromDataStore];
    
    return self;


- (void)loadCategoriesFromDataStore
    
    NSFetchRequest* request = [Category fetchRequest];
    NSSortDescriptor* descriptor = [NSSortDescriptor sortDescriptorWithKey:@"categoryId" ascending:YES];
    [request setSortDescriptors:[NSArray arrayWithObject:descriptor]];
    _categories = [Category objectsWithFetchRequest:request];


- (void)loadNewsFromDataStore
    
    NSFetchRequest* request = [News fetchRequest];
    NSSortDescriptor* descriptor = [NSSortDescriptor sortDescriptorWithKey:@"createdAt" ascending:NO];
    [request setSortDescriptors:[NSArray arrayWithObject:descriptor]];
    _news = [News objectsWithFetchRequest:request];


- (void)loadCategories 

    // Load the object model via RestKit
    RKObjectManager *objectManager = [RKObjectManager sharedManager];
    [objectManager loadObjectsAtResourcePath:@"[link-to-JSON]" delegate:self];


- (void)loadNews 

    // Load the object model via RestKit
    RKObjectManager *objectManager = [RKObjectManager sharedManager];
    [objectManager loadObjectsAtResourcePath:@"[link-to-JSON]" delegate:self];


- (void)objectLoader:(RKObjectLoader*)objectLoader didLoadObjects:(NSArray*)objects 
    [[NSUserDefaults standardUserDefaults] synchronize];
    [self loadCategoriesFromDataStore];
    [self loadNewsFromDataStore];

任何想法我做错了什么?

注意: 当有 15 个新闻时,它似乎也将 30 行保存到连接表中,我不知道这是否是连接表的正常行为。

更新:它还映射了连接表中错误的类别 ID(即类别 66,空行)。

更新 2: JSON 获取我的类别 "categories":[...], "id":1, [...]

的请求

【问题讨论】:

你能用下面这行告诉我它返回的数字是多少:NSNumber* count = [Category numberOfEntities];。如果返回 30,那么一切都很好。忘记关系(连接)表,如果您的映射正确,核心数据应该正确管理它。 NSNumber* news = [News numberOfEntities] 也应该是 15。 News 返回 15,并且似乎有效。但是类别第一次(在干净的数据库上)返回 36(JSON 中应该有 6 个类别),我第二次运行它是 66 等等。并且值为 NULL。 【参考方案1】:

这一行是错误的:

[categoryMapping mapKeyPath:@"id" toAttribute:@"categoryId"];

应该是

[categoryMapping mapKeyPath:@"category_id" toAttribute:@"categoryId"];

编辑: 您拥有的对象映射将映射两种 JSON 格式。

1) "categories":["id":7,"id":12] 当你有资源路径@"[path-to-JSON]"

2) "news":["id":5, "categories":["id":7]] 当你有资源路径 @"[path-to-JSON]"

(顺便说一下,我认为这些实际路径是不同的)

任何其他内容(例如您在问题顶部发布的 JSON)都不起作用。您看到的问题是因为在您的 JSON 中找不到主键属性,所以当对象保存到核心数据时,会创建一个没有主键的新实体。

【讨论】:

嗯,我不确定,id 是我的 JSON 中的 PK,它映射到我数据库中的 categoryId,然后 categoryId 也用作 RestKit 的 primaryKeyAttribute,以防止重复。 没有你的 JSON 是这个 "categories":["category_id":1,"category_id":4]。 category_id 是要映射到核心数据 PK categoryId 的服务器 PK 的关键路径。 是的,但这是我的新闻 JSON 请求中的外键,在类别请求中,PK 看起来像这样:... "id":1 ...,我映射到。 那么您在问题中发布的 JSON 是错误的。请为这两个请求发布 JSON。如果每个PK都不一样,你需要两张不同的地图。 好的,我已将 JSON 添加到我原来的问题中。

以上是关于RestKit 多对多关系在连接表中保存新行,在主表中保存空值的主要内容,如果未能解决你的问题,请参考以下文章

Laravel 多对多关系在哪里保存项目总数? [关闭]

RestKit 创建多对多关系

推进:没有交叉表的多对多关系

保存到多对多关系

RestKit 与 Core Data 多对多:它有效,但我做得对吗?

Laravel - 将数据保存到多对多关系