Golang中如何使用GORM创建记录并关联到另一张表的新建ID

Golang中如何使用GORM创建记录并关联到另一张表的新建ID 我有以下表结构:

type OldData struct {
	Name string
	Date time.Time
}

type NewData struct {
	gorm.Model
	Name string
}

type History struct {
	ID uint
	Date time.Time
}

那么我遇到的情况类似于这样:

oldData := &OldData{
	Name: "Julia",
	Date: time.Now(),
}

newData := &NewData{
	Name: oldData.Name,
}

history := &History{
	Date: oldData.Date,
}

我该如何创建新的 newData 行,同时让 history.IDnewData.ID 相同?如何建立一种关系,使得当我删除 newData.ID 行时,history.ID 行也会从历史表中删除?

我正在寻找一种方法来关联存储在两个不同表中的 newDatahistorydb.Create(newData)


更多关于Golang中如何使用GORM创建记录并关联到另一张表的新建ID的实战教程也可以访问 https://www.itying.com/category-94-b0.html

8 回复

但这需要两次数据库查询,一次获取 history.ID,另一次创建 newData。我希望(如果可能的话)只进行一次直接查询。

更多关于Golang中如何使用GORM创建记录并关联到另一张表的新建ID的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html


NewData 和 History 总是在同一时间创建,我的问题在于创建新记录时如何关联 ID 和日期。两个表拥有相同数量的 ID,你的第二个方案看起来非常接近我正在寻找的解决方案,能请你展示一些代码吗?

您需要在 NewData 结构体中添加 historyID 字段。 检查这行代码

newData := NewData { Bame : "Your Name", HistoryID : history.ID }
type NewData struct {
    gorm.Model
    Name string
    HistoryID uint64
}

解决方案:

type NewData struct {
	gorm.Model
	Name string
    // 使用 ID 作为外键
    History History `gorm:"foreignKey:ID;constraint:OnUpdate:CASCADE,OnDelete:SET NULL"`
}

type History struct {
	ID uint
	Date time.Time
}

newData := &NewData{
    Name: "Julia",
    History: History{
        Date: time.Now(),
    },
}

// 将在 NewData 和 History 表中同时创建具有相同 ID 的两行数据。
db.Create(newData)

我看到一些GORM的说明做了类似这样的事情:

type NewData struct {
	gorm.Model
	Name string
	Date time.Time gorm:"what I do here?"
}

newData := &NewData{
	Name: "someName",
    // 期望Date存储在另一个表中,而不是NewData表,
    // 但使用与NewData相同的ID。
	Date: time.Now(),
}

// 因此,当执行此语句时,NewData只有name列,
// 而Date存储在我们关联的另一个表(History结构体)中,
// 问题是我不知道这是如何实现的。
db.Create(&newData)

根据您描述的情况,HistoryNewData 必须拥有相同数量的记录,并且我猜测 Id 字段是自增的,因此很可能出现相同记录序号对应不同 ID 的情况。您可以这样做:

  • NewDataHistory 合并到一个表中(我不确定这是否可行,因为我不了解您的全部业务需求)。
  • history 表中添加一个外键,以建立与 NewData 表的关系。这样一来,即使它们没有相同的 ID 也没关系,因为您可以确保能从 History 表访问到 NewData 表中正确的记录。

以上只是我的一点浅见。

我认为你可以采用以下方法:

  1. 在历史记录的ID字段上添加此注解
ID uint64 `gorm:"primary_key;auto_increment;not_null"`

你也可以从NewData结构体开始,只需按照上述定义添加ID字段。

  1. 为历史记录表执行创建操作
history := History { Date :  time.Now() }
result := db.Create(&history)
  1. 现在历史记录已获得最新的ID,因此为你的NewData结构体分配一个ID字段并创建记录
newData := NewData { Bame : “Your Name”, historyID : history.ID }
result := db.Create(&newData)

在Golang中使用GORM实现这种关联,可以通过外键约束和关联模式来完成。以下是具体的实现方案:

// 首先修改History结构体,添加NewData的外键引用
type History struct {
    ID uint
    Date time.Time
    NewDataID uint // 添加外键字段
    NewData NewData // 添加关联关系
}

// 创建记录并建立关联
func CreateWithHistory(db *gorm.DB, oldData *OldData) error {
    // 开启事务确保数据一致性
    return db.Transaction(func(tx *gorm.DB) error {
        // 创建newData记录
        newData := &NewData{
            Name: oldData.Name,
        }
        if err := tx.Create(newData).Error; err != nil {
            return err
        }

        // 创建history记录,关联newData的ID
        history := &History{
            Date: oldData.Date,
            NewDataID: newData.ID, // 设置外键
        }
        if err := tx.Create(history).Error; err != nil {
            return err
        }

        return nil
    })
}

// 或者使用GORM的关联创建功能
func CreateWithAssociation(db *gorm.DB, oldData *OldData) error {
    newData := &NewData{
        Name: oldData.Name,
        History: &History{ // 直接关联History
            Date: oldData.Date,
        },
    }
    
    return db.Create(newData).Error
}

// 要启用级联删除,需要在NewData结构体中定义关联
type NewData struct {
    gorm.Model
    Name string
    History History `gorm:"constraint:OnDelete:CASCADE;"` // 添加级联删除约束
}

// 删除操作会自动级联删除关联的history记录
func DeleteWithCascade(db *gorm.DB, newDataID uint) error {
    return db.Delete(&NewData{}, newDataID).Error
}

// 查询时也可以预加载关联的history
func GetWithHistory(db *gorm.DB, id uint) (*NewData, error) {
    var newData NewData
    err := db.Preload("History").First(&newData, id).Error
    return &newData, err
}

对于自动迁移,GORM会自动创建外键约束:

// 自动迁移表结构
db.AutoMigrate(&OldData{}, &NewData{}, &History{})

// 或者手动指定外键关系
db.SetupJoinTable(&NewData{}, "History", &History{})

这个方案通过外键约束确保了数据完整性,并通过级联删除实现了当删除newData记录时自动删除关联的history记录。

回到顶部