Search code examples
goforeign-keysgo-gorm

Foreign key not getting updated in GORM


I have two tables one is company

type Company struct {
    Id        uuid.UUID `gorm:"column:id;primaryKey;"`
    CreatedAt time.Time `gorm:"index;column:createdAt"`
    UpdatedAt time.Time `gorm:"index;column:updatedAt"`
    Name      string    `gorm:"column:name" binding:"required"`
}

and the other is product_entitlement

type ProductEntitlement struct {
ID        uuid.UUID
CreatedAt time.Time `gorm:"index;column:createdAt"`
UpdatedAt time.Time `gorm:"index;column:updatedAt"`
Type       string    `gorm:"column:type" binding:"required"`
CompanyID  uuid.UUID `gorm:"column:companyId;size:36"`
Company    Company   `gorm:"foreignKey:CompanyID"`
}

The CompanyID is a foreign key. CompanyID contains the value from Company.Id

When the upsert is done, everytime it is inserting a new row. here is the code we are using

func UpdateEntitlement(c *gin.Context) {
cid := c.Param("companyId")
    id := c.Param("entitlementId")
    eid := uuid.MustParse(id)
    log.Println(eid)
    uid := uuid.MustParse(cid)
    log.Println(uid)
    var entitlementRequest entities.ProductEntitlement
    if err := c.BindJSON(&entitlementRequest); err != nil {
        log.Println(err)
        fmt.Println("ERROR: ", err)
        c.JSON(400, gin.H{"error": "Invalid JSON format"})
        return
    }
    if err := database.DB.Clauses(clause.OnConflict{
        Columns:   []clause.Column{{Name: "id"}},
        UpdateAll: true,
    }).Create(&entitlementRequest).Error; err != nil {
        log.Println(err)
    }
}

but it is always failing and giving the error as

 Error 1452 (23000): Cannot add or update a child row: a foreign key constraint fails (`crud_demo`.`product_entitlement`, CONSTRAINT `fk_company_product_entitlements` FOREIGN KEY (`companyId`) REFERENCES `company` (`id`))

I would like to update the product_entitlement if the id is present, else create a new one

the url is as follows, http://localhost:8080/company/{{companyId}}/product/{{companyId}} and PUT method is used the body is

{"type" : "automatic"}


Solution

  • In case if it helps someone, we can use the FirstOrCreate function to check if the id exists to update and if not present will create a new one.

    To assign foreign key we need to assign the value to the related table as,

    entitlementRequest.CompanyID = uid

    func UpdateEntitlement(c *gin.Context) {
        cid := c.Param("companyId")
        uid := uuid.MustParse(cid)
        eid := c.Param("entitlementId")
        nid := uuid.MustParse(eid)
        var entitlementRequest entities.ProductEntitlement
        entitlementRequest.CompanyID = uid
    
        if err := c.BindJSON(&entitlementRequest); err != nil {
            fmt.Println("ERROR: ", err)
            c.JSON(400, gin.H{"error": "Invalid JSON format"})
            return
        }
        if err := database.DB.Where("id = ?", nid).
            Assign(entitlementRequest).
            FirstOrCreate(&entitlementRequest).Error; err != nil {
            c.JSON(http.StatusBadRequest, gin.H{"error": "Record not found!"})
            return
        }
        c.JSON(http.StatusOK, gin.H{"error": "Product entitlement upserted successfully"})
    }