1 回答

TA貢獻1831條經驗 獲得超9個贊
如何建立關系并不明顯,因為似乎您正在為 EmployeeGroup 和 EmployeeRole 使用匿名嵌入式結構,并且您尚未包含這些結構的代碼。我將假設您已經正確設置了它,并且gorm很樂意處理涉及匿名嵌入式結構的關系。
我還假設您指的是 BelongsTo 關系,否則您將在哪里放置外鍵以將 Employee 表與角色或組表鏈接起來?很明顯,外鍵不在最后兩個中。
因此,您已經獲得了一個 Employee 結構,當給定無效的 GroupID 或 RoleID 時,您有兩種選擇:在 ID 不存在時拒絕操作,或者使用給定的 ID 創建新的角色/組。第一個是更理智和通常的處理事情的方式,但gorm也可以做到。
對于第一個,如果您的數據庫中有外鍵檢查,則可以執行以下操作:
// First make sure that EmployeeRoleID and EmployeeGroupID are set err := db.Omit("EmployeeRole", "EmployeeGroup").Create(employee).Error
如果 EmployeeGroup.ID 或 EmployeeRole.ID 不存在,則會發生外鍵沖突,并且您將收到錯誤。您可以檢查錯誤并推斷出它與外鍵有關,然后返回相應的 API 級錯誤。
您可能會發現此錯誤檢查有點麻煩,具體取決于您使用的數據庫。老實說,在保存實體之前觸發一堆額外的關系驗證查詢是非常常見的,所以在這種情況下,不要對必須這樣做感到驚訝。
另一方面,如果每次都想保存新的角色和組,則可以刪除省略調用,確保每個 ID 為零,然后調用 Create。Gorm 將保存角色和組,為他們提供新 ID,然后在員工記錄中保存指向這些新 ID 的鏈接。
編輯
我嘗試運行您的代碼,并發現了一些問題:
首先,您的輸入 JSON 具有所有 TitleCased 鍵名,但模型結構希望其中很多鍵名都是小寫的。你需要決定其中一個并堅持下去,否則編組和取消marshaling將不起作用。
這同樣適用于 / vs /。在 JSON 中具有一個版本的名稱,在 Go 結構中具有一個版本(如果刪除了標記,它們也可以全部是相同的 TitleCased 版本)。
EmployeeRoleID
EmployeeGroupID
groupID
roleID
json:"blah"
Gorm不喜歡為相關實體嵌入匿名結構,它不會為它們創建外鍵,而是在主表中創建無關的字段,不要這樣做。
您已將 Role 和 Group 的名稱用作復合主鍵的一部分,但這會中斷鍵控,因為您需要在主結構中顯示兩個字段才能使其正常工作,例如 和 ,這違背了擁有單獨實體的目的。如果要在名稱中強制實施唯一性,請改為添加唯一索引。
EmployeeGroupID
EmployeeGroupName
事實證明,這僅適用于多對多關系。對于屬于 - 要做的是填寫主結構中的字段,并省略與 的關系。
Omit("Relation.*")
RelationID
Omit("Relation")
下面是有效的模型的簡化版本:
type Employee struct {
PrivateGormModel
Person `gorm:"embedded" json:"Person"`
// ...
RoleID uint
Role EmployeeRole `gorm:"constraint:OnUpdate:CASCADE,OnDelete:SET NULL;"`
}
type EmployeeRole struct {
PrivateGormModel
Title string `gorm:"uniqueIndex"`
}
下面是一個測試用例,它顯示了它是如何工作的,假設有一個配置的:DB *gorm.DB
package main
import (
"encoding/json"
"testing"
"github.com/stretchr/testify/require"
)
var inJSON = `{
"Person": {
"FirstName": "Test"
},
"RoleID": 1
}`
func TestGORM(t *testing.T) {
require := require.New(t)
require.NoError(DB.Migrator().DropTable(&Employee{}, &EmployeeRole{}))
require.NoError(DB.Migrator().AutoMigrate(&Employee{}, &EmployeeRole{}))
emp := Employee{}
json.Unmarshal([]byte(inJSON), &emp)
// create the role to simulate that it exists
role := EmployeeRole{PrivateGormModel{ID: 1}, "Test"}
require.NoError(DB.Create(&role).Error)
// avoid re-saving emp.Role
require.NoError(DB.Omit("Role").Create(&emp).Error)
// if instead the RoleID doesn't exist
emp.RoleID = 5
require.Error(DB.Create(&emp).Error)
}
- 1 回答
- 0 關注
- 94 瀏覽
添加回答
舉報