2014-12-29 36 views
1

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

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来实现的DB模式和我在一片空白上如何分辨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) 
} 

我怎么能说UUID_SHORT()为user_uuid列当实例被保存?

回答

2

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

这可能是不错的找到一种方法,使用gorm为MySQL UUID_SHORT()调用本身,但最终可能需要更多的工作只是为了映射使用的单行值(user_uuid在这种情况下)在model.User(可能需要额外的struct仅用于UUID_SHORT()

因此,使用更简单的方法可能会有所帮助。下面的代码是如何UUID_SHORT()可使用找到一个基本(尽管可能差*)示例的sql package(特别是与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:[email protected](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:[email protected]/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

我最终做了类似的事情,完全忘记了这个问题。感谢您抽出一年半的时间回答它:-) – tobiash

+0

@tobiash很高兴听到它解决了! _(而且这种类型的东西可能还有更高效的方法......)_ – summea