Json 使用gorm创建记录时如何验证归属关系
我有以下型号Json 使用gorm创建记录时如何验证归属关系,json,go,go-gorm,Json,Go,Go Gorm,我有以下型号 type PrivateGormModel struct { ID uint `gorm:"primary_key" json:"id"` CreatedAt time.Time `json:"-"` UpdatedAt time.Time `json:"-"` DeletedAt *time.Time `json:"-"
type PrivateGormModel struct {
ID uint `gorm:"primary_key" json:"id"`
CreatedAt time.Time `json:"-"`
UpdatedAt time.Time `json:"-"`
DeletedAt *time.Time `json:"-"`
}
type Employee struct {
PrivateGormModel
Person `gorm:"embedded" json:"person,omitempty"`
Contact `gorm:"embedded" json:"contact,omitempty"`
Address `gorm:"embedded" json:"address,omitempty"`
AltContact `gorm:"embedded" json:"privateContact,omitempty"`
BankAccount `gorm:"embedded" json:"bankAccount,omitempty"`
EmployeeGroupID uint `json:"groupID"`
EmployeeGroup `json:"group"`
EmployeeRoleID uint `json:"roleID"`
EmployeeRole `json:"role"`
}
func (e Employee) Validate() error {
return validation.ValidateStruct(&e,
validation.Field(&e.Person, validation.Required),
validation.Field(&e.Contact),
validation.Field(&e.Address),
validation.Field(&e.AltContact),
validation.Field(&e.BankAccount),
validation.Field(&e.EmployeeGroup),
validation.Field(&e.EmployeeRole),
)
}
type EmployeeGroup struct {
PrivateGormModel
Title string `json:"title" gorm:"primaryKey;unique"`
}
func (e EmployeeGroup) Validate() error {
return validation.ValidateStruct(&e,
validation.Field(&e.Title, validation.Required, validation.Length(1, 32), validation.Match(regexp.MustCompile(`^[a-zA-Z0-9_ ]*$`))),
)
}
type EmployeeRole struct {
PrivateGormModel
Title string `json:"title" gorm:"primaryKey;unique"`
}
func (e EmployeeRole) Validate() error {
return validation.ValidateStruct(&e,
validation.Field(&e.Title, validation.Required, validation.Length(1, 32), validation.Match(regexp.MustCompile(`^[a-zA-Z0-9_ ]*$`))),
)
}
我的员工组和员工角色都只是一个具有gorm模型和字符串类型标题的结构。我在数据库中有一个id为1的角色,一个id为1的组。这是创建员工的处理程序
func CreateEmployee(db *database.Database) fiber.Handler {
return func(c *fiber.Ctx) error {
employee := new(model.Employee)
if err := c.BodyParser(employee); err != nil {
fmt.Printf("%v", err)
return c.JSON(myResponse.ParsingError())
}
// if err := employee.Validate(); err != nil {
// return c.JSON(myResponse.ValidationError(err))
// }
if result := db.Omit("EmployeeRole.*").Omit("EmployeeGroup.*").Create(&employee); result.Error != nil {
return c.JSON(myResponse.RecordCreateError())
}
return c.JSON(myResponse.RecordCreateSuccess(employee))
}
}
我将输入的JSON解析到如下所示的模型中,并尝试在数据库中创建它
{
"Person":{
"Initials":"",
"FirstName":"",
"MiddleName":"",
"LastName":"",
"DateOfBirth":"",
"Language":""
},
"Address":{
"Country":"",
"Zip":"",
"Number":"0",
"Addition":"",
"Street":"",
"State":"",
"City":""
},
"Contact":{
"Tel":"",
"Mail":"",
"URL":""
},
"BankAccount":{
"Bank":"",
"BIC":"",
"IBAN":"",
"AccountHolder":"",
"Establishment":""
},
"EmployeeRoleID":1,
"EmployeeRole":{
"Title":"Test"
},
"EmployeeGroupID":1,
"EmployeeGroup":{
"Title":"Test"
}
}
这给了我以下的回答
{
"data": {
"id": 7,
"person": {
"initials": "",
"firstName": "",
"middleName": "",
"lastName": "",
"dateOfBirth": "2021-01-05T11:14:38+01:00",
"language": ""
},
"contact": {
"tel": "",
"mail": "",
"url": ""
},
"address": {
"country": "",
"zip": "",
"number": "0",
"addition": "",
"street": "",
"state": "",
"city": ""
},
"privateContact": {
"tel": "",
"mail": "",
"url": ""
},
"bankAccount": {
"bank": "",
"bic": "",
"iban": "",
"accountHolder": "",
"establishment": ""
},
"groupID": 0,
"group": {
"id": 0,
"title": ""
},
"roleID": 0,
"role": {
"id": 0,
"title": ""
}
},
"message": "record created successfully",
"status": "success"
}
即使ID为1的角色记录和ID为1的组记录不存在,也会给出以下响应。如果角色或组不存在,则应该给我一个错误,并且不创建记录。不清楚您是如何建立关系的,因为您似乎正在为EmployeeGroup和EmployeeOLE使用匿名嵌入结构,并且您还没有包含这些结构的代码。我将假设您已经正确地设置了它,并且gorm很乐意处理涉及匿名嵌入式结构的关系 我还将假设您指的是BelongsTo关系,否则,您将把外键放在哪里以将Employee表与Role表或Group表链接?很明显,外键不在最后两个中的任何一个中 因此,您得到了一个Employee结构,当提供了无效的GroupID或RoleID时,您有两个选项:在ID不存在时拒绝操作,或者使用给定的ID创建一个新的角色/组。第一种是比较理智和平常的处理方式,但戈姆也可以这样做 对于第一种情况,如果数据库中有外键检查,则可以执行以下操作:
//首先确保设置了EmployeeRoleID和EmployeeGroupID
err:=db.Omit(“EmployeeRole”、“EmployeeGroup”).Create(employee.Error
如果EmployeeGroup.ID或EmployeeRole.ID不存在,将发生外键冲突,您将得到一个错误。您可以检查错误并推断它与外键有关,然后返回适当的API级别错误
根据所使用的数据库,您可能会发现检查此错误有点麻烦。老实说,在保存实体之前发出一堆额外的关系验证查询是极为常见的,因此在这种情况下必须这样做也不必感到惊讶
另一方面,如果每次都要保存一个新角色和组,可以删除省略调用,确保每个ID为零,然后调用Create。Gorm将保存角色和组,并为其提供新ID,然后在员工记录中保存指向这些新ID的链接
编辑 我尝试运行您的代码,发现了一些问题:
- 首先,您的输入JSON具有所有基于标题的键名,但model struct希望它们中有很多是小写的。你需要决定一个或另一个并坚持下去,否则封送和解封将不起作用
- 同样适用于
/EmployeeRoleID
vsEmployeeGroupID
/groupID
。在JSON中有一个版本的名称,在Go结构中有一个版本(如果您删除了roleID
标记,它们也可以是相同的基于标题的版本)JSON:“blah”
- Gorm不喜欢相关实体的嵌入式匿名结构,它不为它们创建外键,也不在主表中创建无关字段,不要这样做
- 您已将角色和组的名称用作复合主键的一部分,但这会中断键控,因为您需要在主结构中使用两个字段才能使其工作,例如
和EmployeeGroupID
,这与拥有单独实体的目的背道而驰。如果要在名称中强制唯一性,请改为添加唯一索引EmployeeGroupName
- 事实证明,
只适用于多对多关系。For BETH所要做的事情是在主结构中填写省略(“Relation.*”)
字段,并使用RelationID
通常省略关系omit(“relationship”)
type Employee结构{
私有模型
Person`gorm:“嵌入式”json:“Person”`
// ...
罗莱德乌因特
角色EmployeeRole`gorm:“约束:OnUpdate:CASCADE,OnDelete:SET NULL;”`
}
类型EmployeeRole结构{
私有模型
标题字符串`gorm:“唯一索引”`
}
这里有一个测试用例,演示了它是如何工作的,假设有一个已配置的DB*gorm.DB
:
主程序包
进口(
“编码/json”
“测试”
“github.com/stretchr/authentic/require”
)
var inJSON=`{
“人”:{
“名字”:“测试”
},
“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:=雇员{}
Unmarshal([]字节(inJSON),&emp)
//创建角色以模拟其存在
角色:=EmployeeRole{PrivateGormModel{ID:1},“Test”}
require.NoError(DB.Create(&role).Error)
//避免重新保存emp.角色
require.NoError(DB.Omit(“角色”).Create(&emp.Error)
//如果RoleID不存在
emp.RoleID=5
require.Error(DB.Create(&emp.Error)
}
请注意,[gorm]标记完全未绑定到Go gorm库。请用[go gorm]代替。实际问题是什么?数据库中的记录未创建,或者输出JSON对象未填充?数据库中的角色和组记录可能不存在。所以,当我创建一个员工时,我猜是这样的。我应该在创建员工之前进行两次数据库查询吗?这取决于您想做什么。如果在创建员工时角色和/或组不存在,您是要创建它们,还是只想使用以前添加的角色和组?您的模型似乎不包含