douqianke7467 2017-05-08 13:09
浏览 416
已采纳

GORM UUID太长

Currently I am using GO-GORM for all of my database queries (mostly CRUD) and I am having some issues inserting a generated UUID into a MySQL database column.

The column is a BINARY(16) as suggested in multiple blogs, the UUID is generated using github.com/satori/go.uuid package for Golang.

I am using GORM's BeforeCreate hook to generate the UUID if one does not already exist on the user, the code that I am using is as follows:

func (u *User) BeforeCreate(scope *gorm.Scope) (err error) {
    if u.UserID == uuid.Nil {
        uuid, err := uuid.NewV4().MarshalBinary()
        scope.SetColumn("user_id", uuid)
    }
}

I have also used len to get the length that MarshalBinary outputs and it returns as 16.

The error I get from GORM when trying to insert the UUID into MySQL is as follows:

(Error 1406: Data too long for column 'user_id' at row 1)

I have also fmt.Println(uuid) to see the results and they are also as follows (obviosuly changes as the UUID is generated every insert)

[93 132 59 55 102 96 72 35 137 185 34 21 195 88 213 127]

My MYSQL schema is as follows also:

CREATE TABLE users
(
    id INT(10) unsigned PRIMARY KEY NOT NULL AUTO_INCREMENT,
    created_at TIMESTAMP,
    updated_at TIMESTAMP,
    deleted_at TIMESTAMP,
    user_id BINARY(16) NOT NULL,
    username VARCHAR(255) NOT NULL,
    password VARCHAR(255),
    firstname VARCHAR(255),
    lastname VARCHAR(255),
    email VARCHAR(255),
    address_id VARCHAR(255)
);
CREATE INDEX idx_users_deleted_at ON users (deleted_at);
CREATE UNIQUE INDEX username ON users (username);
CREATE UNIQUE INDEX user_id ON users (user_id);

I have tried different methods and libraries to generate UUIDs and convert them to binary to insert with similar results.

  • 写回答

1条回答 默认 最新

  • douhui8163 2017-05-08 23:54
    关注

    I think the problem is in the definition of model User. To save the GUID as 16-bytes binary, you need to define the UserID column as []byte not uuid.UUID.

    type User struct {
        //other fields ..
        UserID    []byte
    
        //other fields ...
    }
    
    func (u *User) BeforeCreate(scope *gorm.Scope) (err error) {
        if u.UserID == nil {
            uuid, err := uuid.NewV4().MarshalBinary()
            scope.SetColumn("user_id", uuid)
        }
        return nil
    }
    

    If you define the field as uuid.UUID, gorm "misinterpreted" the field as string and then insert that string into the database as binary. For example, the following UUID,

    uuid: 16ac369b-e57f-471b-96f6-1068ead0bf98
    //16-bytes equivalent
    bytes: [22 172 54 155 229 127 71 27 150 246 16 104 234 208 191 152]
    

    will be inserted to database as the ASCII codes of the UUID which are

    0x31 0x36 0x61 0x63 0x33 0x36 0x39 0x62 0x2D 0x65 ...
    ('1' '6'  'a'  'c'  '3'  '6'  '9'  'b'  '-'  'e'  ...)
    

    which are 36-bytes in length, thus you're getting Error 1406: ...

    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论

报告相同问题?

悬赏问题

  • ¥15 word样式右侧翻页键消失
  • ¥15 springboot+vue 集成keycloak sso到阿里云
  • ¥15 win7系统进入桌面过一秒后突然黑屏
  • ¥30 backtrader对于期货交易的现金和资产计算的问题
  • ¥15 求C# .net4.8小报表工具
  • ¥15 安装虚拟机时出现问题
  • ¥15 Selenium+docker Chrome不能运行
  • ¥15 mac电脑,安装charles后无法正常抓包
  • ¥18 visio打开文件一直显示文件未找到
  • ¥15 请教一下,openwrt如何让同一usb储存设备拔插后设备符号不变?