golang调用mysql函数

时间:2014-12-29 18:24:21

标签: mysql sql go go-gorm

我有一个现有的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实现数据库模型,并且我在如何告诉gorm和数据库/ sql在创建新的User实例时调用UUID_SHORT()时写了一个空白。

来自model / 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"
}

来自model / 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()?

1 个答案:

答案 0 :(得分:3)

为了在UUID_SHORT()调用中调用MySQL的model.User,您似乎需要在到达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可能已经提供了处理此问题的方法)。