go-gorm / gorm

The fantastic ORM library for Golang, aims to be developer friendly
https://gorm.io
MIT License
36.56k stars 3.91k forks source link

Create HasOne generate Update SQL instead of Insert #1608

Closed Jennal closed 6 years ago

Jennal commented 7 years ago

What version of Go are you using (go version)?

go version go1.9 linux/amd64

Which database and its version are you using?

Server version: 5.5.52-MariaDB MariaDB Server

What did you do?

I created 2 table which are HasOne relation, user and user_propery. And I put a tag gorm:"primary_key" to primary key of user_property. Then create user, which I expect user created and user_property created. But actual result is user created, and user_property not created, update sql runs.

Data struct

DROP TABLE IF EXISTS `user` ;

CREATE TABLE IF NOT EXISTS `user` (
  `id` INT NOT NULL AUTO_INCREMENT,
  `created_at` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
  `updated_at` TIMESTAMP NULL,
  `deleted_at` TIMESTAMP NULL,
  `last_login_time` TIMESTAMP NOT NULL DEFAULT 0,
  `username` VARCHAR(45) NOT NULL,
  `password` VARCHAR(45) NOT NULL,
  `token` VARCHAR(45) NOT NULL,
  `is_guest` TINYINT NOT NULL DEFAULT 0,
  `token_expire_at` TIMESTAMP NOT NULL DEFAULT 0,
  `type` SMALLINT NOT NULL DEFAULT 0 COMMENT '0: normal player\n1: developer',
  PRIMARY KEY (`id`),
  UNIQUE INDEX `idx_username` (`username` ASC),
  UNIQUE INDEX `idx_token` (`token` ASC),
  INDEX `idx_deleted_at` (`deleted_at` ASC))
ENGINE = InnoDB
DEFAULT CHARACTER SET = utf8;

-- -----------------------------------------------------
-- Table `user_property`
-- -----------------------------------------------------
DROP TABLE IF EXISTS `user_property` ;

CREATE TABLE IF NOT EXISTS `user_property` (
  `user_id` INT NOT NULL,
  `created_at` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
  `updated_at` TIMESTAMP NULL,
  `deleted_at` TIMESTAMP NULL,
  `nickname` VARCHAR(50) NOT NULL,
  `power` INT NOT NULL DEFAULT 0,
  `` VARCHAR(45) NULL,
  PRIMARY KEY (`user_id`),
  INDEX `idx_deleted_at` (`deleted_at` ASC))
ENGINE = InnoDB
DEFAULT CHARACTER SET = utf8;

Code

package main

import (
    "fmt"
    "time"

    "github.com/jinzhu/gorm"
    _ "github.com/jinzhu/gorm/dialects/mysql"
)

var db *gorm.DB

func init() {
    var err error
    // db, err = gorm.Open("mysql", "gorm:gorm@/dbname?charset=utf8&parseTime=True")
    db, err = gorm.Open("mysql", "dbuser:DbUser$200@tcp(192.168.1.200:3306)/dhgame?charset=utf8&parseTime=True&loc=Local")
    if err != nil {
        panic(err)
    }
    db.SingularTable(true)
    db.LogMode(true)
}

type ModelTimes struct {
    CreatedAt time.Time
    UpdatedAt time.Time
    DeletedAt *time.Time `sql:"index"`
}

type UserProperty struct {
    ModelTimes
    UserID   uint `gorm:"primary_key"` //if I put tag  here, Insert User will do Update user_property instead of Insert
    Nickname string
    Power    uint
}

type User struct {
    gorm.Model
    UserProperty  UserProperty `gorm:"ForeignKey:UserID"`
    LastLoginTime time.Time
    Username      string
    Password      string
    Token         string
    IsGuest       bool
    TokenExpireAt time.Time
    Type          uint16
}

func main() {
    user := &User{
        Model: gorm.Model{
            CreatedAt: time.Now(),
        },
        LastLoginTime: time.Now(),
        Username:      "123456",
        Password:      "1234",
        Token:         "123456",
        IsGuest:       false,
        TokenExpireAt: time.Date(2018, 1, 1, 0, 0, 0, 0, time.Local),
        UserProperty: UserProperty{
            Nickname: "1234",
            Power:    100,
        },
    }
    fmt.Println(db.Create(user).Error)
}

Log

?[35m(main.go:65)?[0m
?[33m[2017-09-11 17:30:27]?[0m  ?[36;1m[0.00ms]?[0m  INSERT INTO `user` (`created_at`,`updated_at`,`deleted_at`,`last_login_time`,`username`,`password`,`token`,`is_guest`,`token_expire_at`,`type`) VALUES ('
2017-09-11T17:30:27+08:00','2017-09-11T17:30:27+08:00','<nil>','2017-09-11T17:30:27+08:00','123456','1234','123456','false','2018-01-01T00:00:00+08:00','0')

?[35m(main.go:65)?[0m
?[33m[2017-09-11 17:30:27]?[0m  ?[36;1m[0.00ms]?[0m  UPDATE `user_property` SET `created_at` = '0001-01-01T00:00:00Z', `updated_at` = '2017-09-11T17:30:27+08:00', `deleted_at` = '<nil>', `nickname` = '1234'
, `power` = '100'  WHERE `user_property`.deleted_at IS NULL AND `user_property`.`user_id` = '107'
jinzhu commented 6 years ago

Should not use foreign key as primary key for UserProperty