Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/flash/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Json 使用gorm创建记录时如何验证归属关系_Json_Go_Go Gorm - Fatal编程技术网

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
    /
    EmployeeGroupID
    vs
    groupID
    /
    roleID
    。在JSON中有一个版本的名称,在Go结构中有一个版本(如果您删除了
    JSON:“blah”
    标记,它们也可以是相同的基于标题的版本)
  • Gorm不喜欢相关实体的嵌入式匿名结构,它不为它们创建外键,也不在主表中创建无关字段,不要这样做
  • 您已将角色和组的名称用作复合主键的一部分,但这会中断键控,因为您需要在主结构中使用两个字段才能使其工作,例如
    EmployeeGroupID
    EmployeeGroupName
    ,这与拥有单独实体的目的背道而驰。如果要在名称中强制唯一性,请改为添加唯一索引
  • 事实证明,
    省略(“Relation.*”)
    只适用于多对多关系。For BETH所要做的事情是在主结构中填写
    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对象未填充?数据库中的角色和组记录可能不存在。所以,当我创建一个员工时,我猜是这样的。我应该在创建员工之前进行两次数据库查询吗?这取决于您想做什么。如果在创建员工时角色和/或组不存在,您是要创建它们,还是只想使用以前添加的角色和组?您的模型似乎不包含