GoFrame 高級特性-字段映射

2022-04-02 14:05 更新

在對數(shù)據(jù)進行寫入、更新使用諸如?Fields/Data/Scan?方法時,如果給定的參數(shù)為?map/struct?類型,給定參數(shù)的鍵名/屬性名稱將會自動按照忽略大小寫及特殊字符的方式與數(shù)據(jù)表的字段進行自動識別映射。

這也是為什么使用?GoFrame ORM?執(zhí)行數(shù)據(jù)庫操作時會出現(xiàn) ?SHOW FULL COLUMNS FROM `xxx`? 語句的原因,該語句每張表只會執(zhí)行一次,隨后緩存結果到內存。

匹配規(guī)則的示例:

Map鍵名     字段名稱     是否匹配
nickname   nickname      match
NICKNAME   nickname      match
Nick-Name  nickname      match
nick_name  nickname      match
nick name  nickname      match
NickName   nickname      match
Nick-name  nickname      match
nick_name  nickname      match
nick name  nickname      match

我們來看一個例子,我們實現(xiàn)一個查詢用戶基本信息的一個接口,這個用戶是一個醫(yī)生。

1、我們有兩張表,一張?user?表,大概有30個字段;一張?doctor_user?表,大概有80多個字段。

2、?user?是用戶基礎表,包含用戶的最基礎信息;?doctor_user?是基于?user?表的業(yè)務擴展表,特定用戶角色的表,與?user?表是一對一關系。

3、我們有一個?GRPC?的接口,接口定義是這樣的(為方便演示,這里做了一些簡化):

  • ?GetDoctorInfoRes?

// 查詢接口返回數(shù)據(jù)結構
type GetDoctorInfoRes struct {
	UserInfo             *UserInfo   `protobuf:"bytes,1,opt,name=UserInfo,proto3" json:"UserInfo,omitempty"`
	DoctorInfo           *DoctorInfo `protobuf:"bytes,2,opt,name=DoctorInfo,proto3" json:"DoctorInfo,omitempty"`
	XXX_NoUnkeyedLiteral struct{}    `json:"-"`
	XXX_unrecognized     []byte      `json:"-"`
	XXX_sizecache        int32       `json:"-"`
}

  • ?UserInfo?

// 用戶基礎信息
type UserInfo struct {
	Id                   uint32   `protobuf:"varint,1,opt,name=id,proto3" json:"id,omitempty"`
	Avatar               string   `protobuf:"bytes,2,opt,name=avatar,proto3" json:"avatar,omitempty"`
	Name                 string   `protobuf:"bytes,3,opt,name=name,proto3" json:"name,omitempty"`
	Sex                  int32    `protobuf:"varint,4,opt,name=sex,proto3" json:"sex,omitempty"`
	XXX_NoUnkeyedLiteral struct{} `json:"-"`
	XXX_unrecognized     []byte   `json:"-"`
	XXX_sizecache        int32    `json:"-"`
}

  • ?DoctorInfo?

// 醫(yī)生信息
type DoctorInfo struct {
	Id                   uint32   `protobuf:"varint,1,opt,name=id,proto3" json:"id,omitempty"`
	Name                 string   `protobuf:"bytes,3,opt,name=name,proto3" json:"name,omitempty"`
	Hospital             string   `protobuf:"bytes,4,opt,name=hospital,proto3" json:"hospital,omitempty"`
	Section              string   `protobuf:"bytes,6,opt,name=section,proto3" json:"section,omitempty"`
	Title                string   `protobuf:"bytes,8,opt,name=title,proto3" json:"title,omitempty"`
	XXX_NoUnkeyedLiteral struct{} `json:"-"`
	XXX_unrecognized     []byte   `json:"-"`
	XXX_sizecache        int32    `json:"-"`
}

4、查詢接口實現(xiàn)代碼

// 查詢醫(yī)生信息
func (s *Service) GetDoctorInfo(ctx context.Context, req *pb.GetDoctorInfoReq) (res *pb.GetDoctorInfoRes, err error) {
    // Protobuf返回數(shù)據(jù)結構
	res = &pb.GetDoctorInfoRes{}
	// 查詢醫(yī)生信息
    // SELECT `id`,`avatar`,`name`,`sex` FROM `user` WHERE `user_id`=xxx
	err = dao.PrimaryDoctorUser.
		Ctx(ctx).
		Fields(res.DoctorInfo).
		Where(dao.PrimaryDoctorUser.Columns.UserId, req.Id).
		Scan(&res.DoctorInfo)
	if err != nil {
		return
	}
	// 查詢基礎用戶信息
    // SELECT `id`,`name`,`hospital`,`section`,`title` FROM `doctor_user` WHERE `id`=xxx
	err = dao.PrimaryUser.
		Ctx(ctx).
		Fields(res.DoctorInfo).
		Where(dao.PrimaryUser.Columns.Id, req.Id).
		Scan(&res.UserInfo)
	return res, err
}

當我們調用?GetDoctorInfo?執(zhí)行查詢時,將會向數(shù)據(jù)庫發(fā)起兩條?SQL?查詢,例如:

SELECT `id`,`avatar`,`name`,`sex` FROM `user` WHERE `user_id`=1
SELECT `id`,`name`,`hospital`,`section`,`title` FROM `doctor_user` WHERE `id`=1

可以看到:

  • 使用?Fields?方法時,參數(shù)類型為?struct?或者?*struct?,?ORM?將會自動將?struct?的屬性名稱與數(shù)據(jù)表的字段名稱做自動映射匹配,當映射匹配成功時只會查詢特定字段數(shù)據(jù),而不存在的屬性字段將會被自動過濾。
  • 使用?Scan?方法時(也可以用?Struct/Structs?),參數(shù)類型為?*struct?或者?**struct?,查詢結果將會自動與?struct?的屬性做自動映射匹配,當映射匹配成功時會自動做轉換賦值,否則不會對參數(shù)的屬性做任何處理。


以上內容是否對您有幫助:
在線筆記
App下載
App下載

掃描二維碼

下載編程獅App

公眾號
微信公眾號

編程獅公眾號