【问题标题】:golang calling mysql functiongolang调用mysql函数
【发布时间】:2015-02-25 22:38:30
【问题描述】:

我有一个现有的 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 和 database/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()?

【问题讨论】:

    标签: mysql sql go go-gorm


    【解决方案1】:

    为了在您的model.User 调用中调用MySQL 的UUID_SHORT(),您似乎需要在到达testutil.DB.Create(&user) 行之前对数据库进行额外的SQL 调用。

    找到一种将gorm 用于MySQL UUID_SHORT() 调用本身的方法可能会很好,但这可能最终需要更多的工作来映射单个行值(在本例中为user_uuid)以供使用在您的model.User(可能需要额外的struct 仅用于UUID_SHORT()

    因此,使用更简单的方法可能会有所帮助。下面的代码是一个基本的(虽然可能很差*)示例,说明如何使用sql package 找到UUID_SHORT()(特别是在这种情况下使用get_uuid_short() 用户定义的函数):

    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)
    }
    

    在 MySQL 表中有这样的结果:

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

    *注意:此代码可能无法解决多个用户同时调用 get_uuid_short() 的时间(尽管 MySQL 可能已经提供了一种处理此问题的方法)。

    【讨论】:

    • 我最终做了类似的事情,完全忘记了这个问题。感谢您在一年 1/2 之后抽出时间来回答它:-)
    • @tobiash 很高兴听到它成功了! (而且可能还有更有效的方法来处理这类事情......)
    猜你喜欢
    • 1970-01-01
    • 2016-03-17
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-12-30
    • 1970-01-01
    • 1970-01-01
    • 2016-05-24
    相关资源
    最近更新 更多