【问题标题】:Gorm creates duplicate in associationGorm 在关联中创建重复项
【发布时间】:2016-09-19 01:33:27
【问题描述】:

我有以下 2 个具有多对多关系的结构。

type Message struct {
    gorm.Model
    Body         string     `tag:"body" schema:"body"`
    Locations    []Location `tag:"locations" gorm:"many2many:message_locations;"`
    TimeSent     time.Time  `tag:"timesent"`
    TimeReceived time.Time  `tag:"timereceived"`
    User         User
}

type Location struct {
    gorm.Model
    PlaceID string  `tag:"loc_id" gorm:"unique"`
    Lat     float64 `tag:"loc_lat"`
    Lng     float64 `tag:"loc_lng"`
}

如果我使用 DB.Create(my_message) 创建消息,一切正常:消息是在 DB 中创建的,还有一个位置,连接 message_locations 表中填充了消息和位置的相应 ID。

我所期待的是,如果位置已经存在于 DB 中(基于传递的 place_id 字段),gorm 将创建消息,检索位置 ID 并填充 message_locations。这不是正在发生的事情。 由于 PlaceID 必须是唯一的,gorm 发现重复的键值违反了唯一约束“locations_place_id_key”并中止了事务。

另一方面,如果我使 PlaceID 不是唯一的,gorm 会创建带有关联的消息,但随后会为 Location 创建另一个重复条目。

我可以在尝试保存消息之前测试该位置是否已经存在:

existsLoc := Location{}
DB.Where("place_id = ?", mssg.Locations[0].PlaceID).First(&existsLoc)

如果为真,则关闭关联:

DB.Set("gorm:save_associations", false).Create(mssg)
DB.Create(mssg)

消息被保存而没有 gorm 抱怨,但是 message_locations 没有被填充。 我可以“手动”填写它,因为我在测试它的存在时检索了位置 ID,但在我看来,它首先违背了使用 gorm 的目的。

我不确定正确的方法可能是什么。我可能遗漏了一些明显的东西,我怀疑我声明结构的方式可能有问题?欢迎提示。

2016 年 3 月 25 日更新

我最终做了以下事情,我很确定这不是最佳的。如果您有更好的想法,请加入。

在测试该位置是否已经存在并且确实存在之后:

// in a transaction
tx := DB.Begin()

// create the message with transaction disabled
if errMssgCreate := tx.Set("gorm:save_associations", false).Create(mssg).Error; errMssgCreate != nil {
            tx.Rollback()
            log.Println(errMssgCreate)
}

// then create the association with existing location
if errMssgLocCreate := tx.Model(&mssg).Association("Locations").Replace(&existLoc).Error; errMssgLocCreate != nil {
            tx.Rollback()
            log.Println(errMssgLocCreate)
}

tx.Commit()

【问题讨论】:

    标签: go go-gorm


    【解决方案1】:

    gorm:"many2many:message_locations;save_association:false"

    越来越接近你想要的。您需要将它放在 Message 的结构定义中。然后假定该字段存在于数据库中,并且只有关联表将填充数据。

    【讨论】:

    • 是的,我想过。而不是根据具体情况执行DB.Set("gorm:save_associations", false)。但它似乎是一个半满而不是半空的杯子。因为那时 Gorm 现在总是假设该领域存在,但我不能依赖它。其他人为此做了issue on the gorm repo。它是开放的。
    猜你喜欢
    • 1970-01-01
    • 2018-02-08
    • 2020-01-15
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-04-24
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多