OOro

关系定义

使用模型方法定义 BelongsTo、HasOne、HasMany、ManyToMany 和动态关系。

Oro 的关系是模型方法,不是结构体字段。这样可以避免 Go 包循环依赖,也让预加载状态明确。

基本形式

func (article Article) Cover() oro.Relation {
    return oro.HasOne(article, "Cover", "Image").
        ForeignKey("ArticleID").
        ReferenceKey("ID")
}

参数含义:

参数 含义
article 当前模型实例
"Cover" 关系名称
"Image" 目标模型名称
ForeignKey 目标侧或当前侧外键
ReferenceKey 被引用的主键或唯一键

BelongsTo

当前模型保存父级 ID:

func (comment Comment) Article() oro.Relation {
    return oro.BelongsTo(comment, "Article", "Article").
        ForeignKey("ArticleID").
        ReferenceKey("ID")
}

HasOne

目标表中有一行指向当前模型:

func (article Article) Cover() oro.Relation {
    return oro.HasOne(article, "Cover", "Image").
        ForeignKey("ArticleID").
        ReferenceKey("ID")
}

HasMany

目标表中有多行指向当前模型:

func (article Article) Comments() oro.Relation {
    return oro.HasMany(article, "Comments", "Comment").
        ForeignKey("ArticleID").
        ReferenceKey("ID")
}

ManyToMany

func (article Article) Tags() oro.Relation {
    return oro.ManyToMany(article, "Tags", "Tag").
        Through("article_tags").
        SourceForeignKey("ArticleID").
        TargetForeignKey("TagID")
}

中间表可以定义为普通模型并注册,这样可以参与结构同步。

动态关系

动态关系适合媒体、评论、标签、审计记录等跨模块资源:

func (article Article) Images() oro.Relation {
    return oro.DynamicHasMany(article, "Images", "Image").
        IDField("OwnerID").
        TypeField("OwnerType").
        TypeValue("Article")
}

动态关系依赖“来源 ID + 来源类型”区分归属。

为什么不放结构体字段

不推荐:

type Article struct {
    Cover *Image
}

推荐:

func (article Article) Cover() oro.Relation { ... }

关系方法的优势:

  • 不需要双向 import 模型包;
  • 未预加载时能明确返回 ErrRelationNotLoaded
  • 关系元数据集中在方法里;
  • 关系写入和查询可以共用同一个定义。
编辑此页