日韩无码专区无码一级三级片|91人人爱网站中日韩无码电影|厨房大战丰满熟妇|AV高清无码在线免费观看|另类AV日韩少妇熟女|中文日本大黄一级黄色片|色情在线视频免费|亚洲成人特黄a片|黄片wwwav色图欧美|欧亚乱色一区二区三区

RELATEED CONSULTING
相關(guān)咨詢
選擇下列產(chǎn)品馬上在線溝通
服務(wù)時間:8:30-17:00
你可能遇到了下面的問題
關(guān)閉右側(cè)工具欄

新聞中心

這里有您想知道的互聯(lián)網(wǎng)營銷解決方案
創(chuàng)新互聯(lián)GoFrame教程:GoFrame 模型關(guān)聯(lián)-ScanList

?gf?的?ORM?沒有采用其他?ORM?常見的?BelongsTo?, ?HasOne?, ?HasMany?, ?ManyToMany?這樣的模型關(guān)聯(lián)設(shè)計,這樣的關(guān)聯(lián)關(guān)系維護(hù)較繁瑣,例如外鍵約束、額外的標(biāo)簽備注等,對開發(fā)者有一定的心智負(fù)擔(dān)。因此?gf?框架不傾向于通過向模型結(jié)構(gòu)體中注入過多復(fù)雜的標(biāo)簽內(nèi)容、關(guān)聯(lián)屬性或方法,并一如既往地嘗試著簡化設(shè)計,目標(biāo)是使得模型關(guān)聯(lián)查詢盡可能得易于理解、使用便捷。

創(chuàng)新互聯(lián)公司堅持“要么做到,要么別承諾”的工作理念,服務(wù)領(lǐng)域包括:做網(wǎng)站、成都網(wǎng)站制作、企業(yè)官網(wǎng)、英文網(wǎng)站、手機(jī)端網(wǎng)站、網(wǎng)站推廣等服務(wù),滿足客戶于互聯(lián)網(wǎng)時代的高州網(wǎng)站設(shè)計、移動媒體設(shè)計的需求,幫助企業(yè)找到有效的互聯(lián)網(wǎng)解決方案。努力成為您成熟可靠的網(wǎng)絡(luò)建設(shè)合作伙伴!

接下來關(guān)于?gf ORM?提供的模型關(guān)聯(lián)實(shí)現(xiàn),從?GF v1.13.6?版本開始提供,目前屬于實(shí)驗(yàn)性特性。

那么我們就使用一個例子來介紹?gf ORM?提供的模型關(guān)聯(lián)吧。

數(shù)據(jù)結(jié)構(gòu)

為簡化示例,我們這里設(shè)計得表都盡可能簡單,每張表僅包含3-4個字段,方便闡述關(guān)聯(lián)關(guān)系即可。

# 用戶表
CREATE TABLE `user` (
  uid int(10) unsigned NOT NULL AUTO_INCREMENT,
  name varchar(45) NOT NULL,
  PRIMARY KEY (uid)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

# 用戶詳情
CREATE TABLE `user_detail` (
  uid  int(10) unsigned NOT NULL AUTO_INCREMENT,
  address varchar(45) NOT NULL,
  PRIMARY KEY (uid)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

# 用戶學(xué)分
CREATE TABLE `user_scores` (
  id int(10) unsigned NOT NULL AUTO_INCREMENT,
  uid int(10) unsigned NOT NULL,
  score int(10) unsigned NOT NULL,
  course varchar(45) NOT NULL,
  PRIMARY KEY (id)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

數(shù)據(jù)模型

根據(jù)表定義,我們可以得知:

  1. 用戶表與用戶詳情是?1:1?關(guān)系。
  2. 用戶表與用戶學(xué)分是?1:N?關(guān)系。
  3. 這里并沒有演示?N:N?的關(guān)系,因?yàn)橄啾容^于?1:N?的查詢只是多了一次關(guān)聯(lián)、或者一次查詢,最終處理方式和?1:N?類似。

那么GOlang的模型可定義如下:

// 用戶表
type EntityUser struct {
    Uid  int    `orm:"uid"`
    Name string `orm:"name"`
}
// 用戶詳情
type EntityUserDetail struct {
    Uid     int    `orm:"uid"`
    Address string `orm:"address"`
}
// 用戶學(xué)分
type EntityUserScores struct {
    Id     int    `orm:"id"`
    Uid    int    `orm:"uid"`
    Score  int    `orm:"score"`
    Course string `orm:"course"`
}
// 組合模型,用戶信息
type Entity struct {
    User       *EntityUser
    UserDetail *EntityUserDetail
    UserScores []*EntityUserScores
}

其中,?EntityUser?, ?EntityUserDetail?, ?EntityUserScores?分別對應(yīng)的是用戶表、用戶詳情、用戶學(xué)分?jǐn)?shù)據(jù)表的數(shù)據(jù)模型。?Entity?是一個組合模型,對應(yīng)的是一個用戶的所有詳細(xì)信息。

數(shù)據(jù)寫入

寫入數(shù)據(jù)時涉及到簡單的數(shù)據(jù)庫事務(wù)即可。

err := db.Transaction(func(tx *gdb.TX) error {
    r, err := tx.Table("user").Save(EntityUser{
        Name: "john",
    })
    if err != nil {
        return err
    }
    uid, err := r.LastInsertId()
    if err != nil {
        return err
    }
    _, err = tx.Table("user_detail").Save(EntityUserDetail{
        Uid:     int(uid),
        Address: "Beijing DongZhiMen #66",
    })
    if err != nil {
        return err
    }
    _, err = tx.Table("user_scores").Save(g.Slice{
        EntityUserScores{Uid: int(uid), Score: 100, Course: "math"},
        EntityUserScores{Uid: int(uid), Score: 99, Course: "physics"},
    })
    return err
})

數(shù)據(jù)查詢

單條數(shù)據(jù)記錄

查詢單條模型數(shù)據(jù)比較簡單,直接使用?Scan?方法即可,該方法會自動識別綁定查詢結(jié)果到單個對象屬性還是數(shù)組對象屬性中。例如:

// 定義用戶列表
var user Entity
// 查詢用戶基礎(chǔ)數(shù)據(jù)
// SELECT * FROM `user` WHERE `name`='john'
err := db.Table("user").Scan(&user.User, "name", "john")
if err != nil {
    return err
}
// 查詢用戶詳情數(shù)據(jù)
// SELECT * FROM `user_detail` WHERE `uid`=1
err := db.Table("user_detail").Scan(&user.UserDetail, "uid", user.User.Uid)
// 查詢用戶學(xué)分?jǐn)?shù)據(jù)
// SELECT * FROM `user_scores` WHERE `uid`=1
err := db.Table("user_scores").Scan(&user.UserScores, "uid", user.User.Uid)

多條數(shù)據(jù)記錄

查詢多條數(shù)據(jù)記錄并綁定數(shù)據(jù)到數(shù)據(jù)模型數(shù)組中,需要使用到?ScanList?方法,該方法會需要用戶指定結(jié)果字段與模型屬性的關(guān)系,隨后底層會遍歷數(shù)組并自動執(zhí)行數(shù)據(jù)綁定。例如:

// 定義用戶列表
var users []Entity
// 查詢用戶基礎(chǔ)數(shù)據(jù)
// SELECT * FROM `user`
err := db.Table("user").ScanList(&users, "User")
// 查詢用戶詳情數(shù)據(jù)
// SELECT * FROM `user_detail` WHERE `uid` IN(1,2)
err := db.Table("user_detail").
       Where("uid", gdb.ListItemValuesUnique(users, "User", "Uid")).
       ScanList(&users, "UserDetail", "User", "uid:Uid")
// 查詢用戶學(xué)分?jǐn)?shù)據(jù)
// SELECT * FROM `user_scores` WHERE `uid` IN(1,2)
err := db.Table("user_scores").
       Where("uid", gdb.ListItemValuesUnique(users, "User", "Uid")).
       ScanList(&users, "UserScores", "User", "uid:Uid")

這其中涉及到兩個比較重要的方法:

1. ?ScanList?

方法定義:

// ScanList converts  to struct slice which contains other complex struct attributes.
// Note that the parameter  should be type of *[]struct/*[]*struct.
// Usage example:
//
// type Entity struct {
// 	   User       *EntityUser
// 	   UserDetail *EntityUserDetail
//	   UserScores []*EntityUserScores
// }
// var users []*Entity
// or
// var users []Entity
//
// ScanList(&users, "User")
// ScanList(&users, "UserDetail", "User", "uid:Uid")
// ScanList(&users, "UserScores", "User", "uid:Uid")
// The parameters "User"/"UserDetail"/"UserScores" in the example codes specify the target attribute struct
// that current result will be bound to.
// The "uid" in the example codes is the table field name of the result, and the "Uid" is the relational
// struct attribute name. It automatically calculates the HasOne/HasMany relationship with given 
// parameter.
// See the example or unit testing cases for clear understanding for this function.
func (m *Model) ScanList(listPointer interface{}, attributeName string, relation ...string) (err error)

該方法用于將查詢到的數(shù)組數(shù)據(jù)綁定到指定的列表上,例如:

  • ?ScanList(&users, "User")?:表示將查詢到的用戶信息數(shù)組數(shù)據(jù)綁定到?users?列表中每一項的?User?屬性上。
  • ?ScanList(&users, "UserDetail", "User", "uid:Uid")?:表示將查詢到用戶詳情數(shù)組數(shù)據(jù)綁定到?users?列表中每一項的?UserDetail?屬性上,并且和另一個?User?對象屬性通過?uid:Uid?的字段:屬性關(guān)聯(lián),內(nèi)部將會根據(jù)這一關(guān)聯(lián)關(guān)系自動進(jìn)行數(shù)據(jù)綁定。其中?uid:Uid?前面的?uid?表示查詢結(jié)果字段中的?uid?字段,后面的?Uid?表示目標(biāo)關(guān)聯(lián)對象中的?Uid?屬性。
  • ?ScanList(&users, "UserScores", "User", "uid:Uid")?:表示將查詢到用戶詳情數(shù)組數(shù)據(jù)綁定到?users?列表中每一項的?UserScores?屬性上,并且和另一個?User?對象屬性通過?uid:Uid?的字段:屬性關(guān)聯(lián),內(nèi)部將會根據(jù)這一關(guān)聯(lián)關(guān)系自動進(jìn)行數(shù)據(jù)綁定。由于?UserScores?是一個數(shù)組類型?[]*EntityUserScores?,因此該方法內(nèi)部可以自動識別到?User?到?UserScores?其實(shí)是?1:N?的關(guān)系,自動完成數(shù)據(jù)綁定。

需要提醒的是,如果關(guān)聯(lián)數(shù)據(jù)中對應(yīng)的關(guān)聯(lián)屬性數(shù)據(jù)不存在,那么該屬性不會被初始化并將保持?nil?。

2. ?ListItemValues/ListItemValuesUnique?

方法定義:

// ListItemValues retrieves and returns the elements of all item struct/map with key .
// Note that the parameter  should be type of slice which contains elements of map or struct,
// or else it returns an empty slice.
//
// The parameter  supports types like:
// []map[string]interface{}
// []map[string]sub-map
// []struct
// []struct:sub-struct
// Note that the sub-map/sub-struct makes sense only if the optional parameter  is given.
func ListItemValues(list interface{}, key interface{}, subKey ...interface{}) (values []interface{})  

// ListItemValuesUnique retrieves and returns the unique elements of all struct/map with key .
// Note that the parameter  should be type of slice which contains elements of map or struct,
// or else it returns an empty slice.
// See gutil.ListItemValuesUnique.
func ListItemValuesUnique(list interface{}, key string, subKey ...interface{}) []interface{}

?ListItemValuesUnique?與?ListItemValues?方法的區(qū)別在于過濾重復(fù)的返回值,保證返回的列表數(shù)據(jù)中不帶有重復(fù)值。這兩個方法都會在當(dāng)給定的列表中包含?struct/map?數(shù)據(jù)項時,用于獲取指定屬性/鍵名的數(shù)據(jù)值,構(gòu)造成數(shù)組?[]interface{}?返回。示例:

  • ?gdb.ListItemValuesUnique(users, "Uid")?用于獲取?users?數(shù)組中,每一個?Uid?屬性,構(gòu)造成?[]interface{}?數(shù)組返回。這里以便根據(jù)?uid?構(gòu)造成?SELECT...IN...?查詢。
  • ?gdb.ListItemValuesUnique(users, "User", "Uid")?用于獲取?users?數(shù)組中,每一個?User?屬性項中的?Uid?屬性,構(gòu)造成?[]interface{}?數(shù)組返回。這里以便根據(jù)?uid?構(gòu)造成?SELECT...IN...?查詢。

文章標(biāo)題:創(chuàng)新互聯(lián)GoFrame教程:GoFrame 模型關(guān)聯(lián)-ScanList
文章出自:http://m.5511xx.com/article/djsgici.html