【发布时间】:2020-03-22 14:03:29
【问题描述】:
我正在尝试使用 golang 和 gorm 在我当前的项目中创建一个新功能。
我在 MySQL 中有以下数据库结构。
UserMaster 表位于层次结构的顶部,其主键列被许多其他表引用,它们自己将其用作主列。 UserLogin 表就是这样的表之一。这不是完美的数据库设计,但这是我将要处理的数据库结构,而且结构不可能改变。
以下是我在 go 中为 UserMaster 和 UserLogin 创建的模型类。
type UserMaster struct {
UserId string `gorm:"column:UserId;PRIMARY_KEY";size:20`
CreatedDate time.Time `gorm:"column:CreatedDate"`
IsActive bool `gorm:"column:IsActive"`
UserLogin UserLogin `gorm:"foreignkey:Id"`
}
type UserLogin struct {
Id string `gorm:"column:Id;PRIMARY_KEY";size:20"`
UserName string `gorm:"column:UserName;unique"`
EmailId string `gorm:"column:EmailId;unique"`
PasswordHash string `gorm:"column:PasswordHash"`
PasswordSalt string `gorm:"column:PasswordSalt"`
LastLoginDate time.Time `gorm:"column:LastLoginDate"`
}
func (UserMaster) TableName() string {
return "usermaster"
}
func (UserLogin) TableName() string {
return "userlogin"
}
我希望通过 gorm 在 UserMaster 和 UserLogin 表中创建行,只需保存完全填充的 UserMaster 实例。
以下是我为此编写的代码。
func main() {
db, err := gorm.Open("mysql", "user:password@tcp(localhost:3306)/ormsample")
if err != nil {
panic("Failed to connect the database.")
}
defer db.Close()
createNewUser(db, "someuser009@yopmail.com", "j;dfasdasdf")
}
func createNewUser(db *gorm.DB, emailId string, password string) UserMaster {
userId := createUserId()
newUser := &UserMaster{}
newUser.UserId = userId
newUser.CreatedDate = time.Now()
newUser.UserLogin = UserLogin{}
newUser.UserLogin.UserName = emailId
newUser.UserLogin.EmailId = emailId
newUser.UserLogin.PasswordHash = password
newUser.UserLogin.PasswordSalt = "SomeSalt"
db.Debug().Model(&newUser).Create(&newUser)
return *newUser
}
func createUserId() string {
uuidWithHyphen := uuid.New()
uuid := strings.Replace(uuidWithHyphen.String(), "-", "", -1)
return strings.ToUpper(uuid[:12])
}
这整个事情按预期工作,这意味着它将记录插入到 UserMaster 和 UserLogin 表中。
问题在于 gorm 执行此数据库操作的方式。以下是终端记录的 SQL 查询(因为我在 gorm db 对象上使用Debug() 函数)。
INSERT INTO `usermaster` (`UserId`,`CreatedDate`,`IsActive`)
VALUES ('1601F7E41E29','2020-03-22 22:24:08',false)
UPDATE `userlogin` SET `UserName` = 'someuser009@yopmail.com',
`EmailId` = 'someuser009@yopmail.com', `PasswordHash` = 'j;dfasdasdf',
`PasswordSalt` = 'SomeSalt', `LastLoginDate` = '0000-00-00 00:00:00'
WHERE `userlogin`.`Id` = '1601F7E41E29'
SELECT * FROM `userlogin` WHERE `userlogin`.`Id` = '1601F7E41E29'
ORDER BY `userlogin`.`Id` ASC LIMIT 1
INSERT INTO `userlogin` (`Id`,`UserName`,`EmailId`,`PasswordHash`,`PasswordSalt`,`LastLoginDate`)
VALUES ('1601F7E41E29','someuser009@yopmail.com','someuser009@yopmail.com',
'j;dfasdasdf','SomeSalt','0000-00-00 00:00:00')
正如您在上面看到的那样,gorm 执行 2 个 INSERT、1 个 UPDATE 和 1 个 SELECT 查询以插入到两个表中,而应该只执行 2 个 INSERT 查询。
我在各种 golang 和 gorm 论坛上对此进行了很多搜索,但没有找到任何可以解释这种行为的东西。
任何解决此问题的帮助/指导/方向将不胜感激。
【问题讨论】:
-
@All 随时询问您是否需要 sql 脚本来创建数据库表。我没有将它们包括在问题中以保持问题的长度适中。
-
如果将
newUser.UserLogin.Id设置为userId而不是将其留空,会发生什么情况? -
@mkopriva 是的..我也试过了......但行为没有改变。它仍然执行 4 个查询。