3

我有一个现有的 mysql 表,它使用 mysql 的UUID_SHORT()函数来生成唯一 ID。该表的简化版本:

CREATE TABLE `users` (
  `user_uuid` bigint(20) unsigned NOT NULL,
  `user_name` varchar(64) NOT NULL
);

一个新用户将通过以下方式创建:

INSERT INTO users (user_uuid, user_name) values (UUID_SHORT(), "new user name");

我开始使用gorm实现 DBs 模型,并且我对如何告诉 gorm 和数据库/sql 在创建新的 User 实例时调用 UUID_SHORT() 持空白。

从模型/users.go:

package model

type User struct {
    UserUUID          uint64     `gorm:"column:user_uuid;primary_key:yes";sql:"notnull;default:uuid_short"`
    UserName          string     `sql:"notnull"`
}

func (user User) TableName() string {
    return "users"
}

来自模型/users_test.go:

package model_test

import (
    "testing"

    ".../model"
    ".../model/testutil"
)

func TestUserCreate(t *testing.T) {
    user := model.User{
        // UserUUID: **HOW DO I CALL UUID_SHORT() HERE?**,
        UserName: "Go Test",
    }
    // testutil.DB is the successful result of gorm.Open("mysql", ...)
    testutil.DB.Create(&user)
}

保存实例时,如何为 user_uuid 列调用 UUID_SHORT()?

4

1 回答 1

3

In order to make a call to MySQL's UUID_SHORT() in your model.User call, it would seem that you'd need to make an additional SQL call to the database before reaching the testutil.DB.Create(&user) line at some point.

It might be nice to find a way to use gorm for the MySQL UUID_SHORT() call itself, but that might end up requiring more work just to map a single row value (user_uuid in this case) for use in your model.User (possibly requiring an additional struct just for UUID_SHORT()).

Therefore, using a simpler approach might help. The following code is a basic (though perhaps poor*) example of how UUID_SHORT() could be found using the sql package (specifically with the get_uuid_short() user-defined function, in this case):

package model_test

import (
    "database/sql"
    _ "github.com/go-sql-driver/mysql"
    "github.com/jinzhu/gorm"
    "github.com/stretchr/testify/assert"
    "log"
    "testing"
)

type User struct {
    UserUUID uint64 `gorm:"column:user_uuid;primary_key:yes";sql:"notnull;default:uuid_short"`
    UserName string `sql:"notnull"`
}

func (user User) TableName() string {
    return "users"
}

func get_uuid_short() uint64 {
    var uuid_short uint64

    /* connect to db using `sql` package */
    db, err := sql.Open("mysql", "username:password@tcp(127.0.0.1:3306)/uuid_test")
    if err != nil {
        log.Fatal(err)
    }

    /* select UUID_SHORT() */
    rows, err := db.Query("select UUID_SHORT()")
    if err != nil {
        log.Fatal(err)
    }
    defer db.Close()

    /* get value of uuid_short */
    for rows.Next() {
        err := rows.Scan(&uuid_short)
        if err != nil {
            log.Fatal(err)
        }
    }

    return uuid_short
}

func TestUserCreate(t *testing.T) {
    user := User{
        UserUUID: get_uuid_short(),    /* get next UUID_SHORT() value */
        UserName: "Go Test",
    }
    db, err := gorm.Open("mysql", "username:password@/uuid_test?charset=utf8&parseTime=True&loc=Local")
    db.Create(&user)
    assert.Nil(t, err)
}

With results like this in the MySQL table:

mysql> select * from users;
+-------------------+-----------+
| user_uuid         | user_name |
+-------------------+-----------+
| 24070794506141712 | Go Test   |
| 24070794506141713 | Go Test   |
| 24070794506141714 | Go Test   |
+-------------------+-----------+
3 rows in set (0.00 sec)

*Note: This code might not address times where multiple users are concurrently calling get_uuid_short() (though MySQL may already provide a way to deal with this).

于 2015-06-19T23:35:42.847 回答