欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

Golang Gorm實(shí)現(xiàn)自定義多態(tài)模型關(guān)聯(lián)查詢

 更新時(shí)間:2024年11月04日 09:07:03   作者:erternalKing  
GORM 是一個(gè)流行的開源 ORM (Object-Relational Mapping) 庫(kù),專為 Go 語(yǔ)言設(shè)計(jì),它簡(jiǎn)化了與 SQL 數(shù)據(jù)庫(kù)的交互,GORM 封裝了數(shù)據(jù)庫(kù)操作,使得開發(fā)者能夠通過(guò)簡(jiǎn)單的鏈?zhǔn)秸{(diào)用來(lái)執(zhí)行 CRUD,本文給大家介紹了Golang Gorm實(shí)現(xiàn)自定義多態(tài)模型關(guān)聯(lián)查詢,需要的朋友可以參考下

一、表結(jié)構(gòu)

CREATE TABLE `orders` (
  `id` int unsigned NOT NULL AUTO_INCREMENT,
  `order_no` varchar(32) NOT NULL DEFAULT '',
  `orderable_id` int unsigned NOT NULL DEFAULT '0',
  `orderable_type` char(30) NOT NULL DEFAULT '',
  `status` tinyint unsigned NOT NULL DEFAULT '0',
  `created_at` datetime NOT NULL,
  `updated_at` datetime NOT NULL,
  `deleted_at` datetime DEFAULT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=6 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci;
 
CREATE TABLE `phone` (
  `id` int unsigned NOT NULL AUTO_INCREMENT,
  `phone_name` varchar(50) NOT NULL DEFAULT '',
  `phone_model` varchar(30) NOT NULL DEFAULT '',
  `status` tinyint unsigned NOT NULL DEFAULT '0',
  `created_at` datetime NOT NULL,
  `updated_at` datetime NOT NULL,
  `deleted_at` datetime DEFAULT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=1003 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci;
 
CREATE TABLE `cars` (
  `id` int unsigned NOT NULL AUTO_INCREMENT,
  `car_name` varchar(50) NOT NULL DEFAULT '',
  `car_model` varchar(30) NOT NULL DEFAULT '',
  `status` tinyint unsigned NOT NULL DEFAULT '0',
  `created_at` datetime NOT NULL,
  `updated_at` datetime NOT NULL,
  `deleted_at` datetime DEFAULT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=1003 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci;

二、接口定義

// LoaderAble 接口定義數(shù)據(jù)加載行為
type LoaderAble interface {
	LoadAble(IDs []int) (map[int]any, error)
}
 
// LoadAbleItem 接口定義了可加載項(xiàng)的通用方法
type LoadAbleItem interface {
	GetAbleType() string        // 獲取類型鍵值
	GetAbleID() int             // 獲取ID
	SetLoadedAbleData(data any) // 設(shè)置加載的數(shù)據(jù)
}

三、模型定義并實(shí)現(xiàn)接口

type Order struct {
	Id            int            `json:"id"`
	OrderNo       string         `json:"order_no"`
	OrderableId   int            `json:"orderable_id"`
	OrderableType string         `json:"orderable_type"`
	Orderable     any            `json:"orderable" gorm:"-"`
	Status        uint8          `json:"status"`
	CreatedAt     *time.Time     `json:"created_at"`
	UpdatedAt     *time.Time     `json:"updated_at"`
	DeletedAt     gorm.DeletedAt `json:"deleted_at"`
}
 
func (tb *Order) TableName() string {
	return "orders"
}
 
func (tb *Order) GetAbleType() string {
	return tb.OrderableType
}
 
func (tb *Order) GetAbleID() int {
	return tb.OrderableId
}
 
func (tb *Order) SetLoadedAbleData(data any) {
	tb.Orderable = data
}
 
 
 
//--------------------------------------分割線--------------------------------------
 
 
type Car struct {
	Id        int            `json:"id"`
	CarName   string         `json:"car_name"`
	CarModel  string         `json:"car_model"`
	Status    uint8          `json:"status"`
	CreatedAt *time.Time     `json:"created_at"`
	UpdatedAt *time.Time     `json:"updated_at"`
	DeletedAt gorm.DeletedAt `json:"deleted_at"`
}
 
func (tb *Car) TableName() string {
	return "cars"
}
 
// CarLoaderAble 實(shí)現(xiàn) Loader 接口
type CarLoaderAble struct{}
 
// LoadAble 具體實(shí)現(xiàn)加載多態(tài)關(guān)聯(lián)邏輯
// IDs 多態(tài)關(guān)聯(lián)類型ID(主要參數(shù))
func (loader *CarLoaderAble) LoadAble(IDs []int) (resultMap map[int]any, err error) {
	IDsLen := len(IDs)
	if IDsLen == 0 {
		return
	}
 
	car := make([]*Car, 0, IDsLen)
	err = mysql.DefaultMysql.Db.Debug().Where("id IN (?) AND status = ?", IDs, 1).Find(&car).Error
	if err != nil {
		return
	}
 
	resultMap = make(map[int]any, IDsLen)
	for _, item := range car {
		resultMap[item.Id] = item
	}
	return
}
 
 
//--------------------------------------分割線--------------------------------------
 
 
type Phone struct {
	Id         int            `json:"id"`
	PhoneName  string         `json:"phone_name"`
	PhoneModel string         `json:"phone_model"`
	Status     uint8          `json:"status" gorm:"column:status"`
	StatusNew  uint8          `json:"status_new" gorm:"-"`
	CreatedAt  *time.Time     `json:"created_at"`
	UpdatedAt  *time.Time     `json:"updated_at"`
	DeletedAt  gorm.DeletedAt `json:"deleted_at"`
}
 
func (tb *Phone) TableName() string {
	return "phone"
}
 
func (tb *Phone) AfterFind(tx *gorm.DB) (err error) {
	tb.StatusNew = tb.Status
	return
}
 
// PhoneLoaderAble 實(shí)現(xiàn) Loader 接口
type PhoneLoaderAble struct{}
 
// LoadAble 具體實(shí)現(xiàn)加載多態(tài)關(guān)聯(lián)邏輯
// IDs 多態(tài)關(guān)聯(lián)類型ID(主要參數(shù))
func (loader *PhoneLoaderAble) LoadAble(IDs []int) (resultMap map[int]any, err error) {
	IDsLen := len(IDs)
	if IDsLen == 0 {
		return
	}
 
	phone := make([]*Phone, 0, IDsLen)
	err = mysql.DefaultMysql.Db.Debug().Where("id IN (?) AND status = ?", IDs, 1).Find(&phone).Error
	if err != nil {
		return
	}
 
	resultMap = make(map[int]any, IDsLen)
	for _, item := range phone {
		resultMap[item.Id] = item
	}
	return
}

四、創(chuàng)建loader預(yù)加載器

// LoaderAbleFactory 用于管理不同類型的加載器
type LoaderAbleFactory struct {
	loaders map[string]LoaderAble
}
 
func NewLoaderAbleFactory() *LoaderAbleFactory {
	return &LoaderAbleFactory{
		loaders: make(map[string]LoaderAble),
	}
}
 
func (f *LoaderAbleFactory) RegisterLoader(typeName string, loader LoaderAble) {
	f.loaders[typeName] = loader
}

五、注冊(cè)loader預(yù)加載器服務(wù)

var (
	loaderAbleFactory *LoaderAbleFactory
)
 
// init 選擇在項(xiàng)目啟動(dòng)初始化時(shí)進(jìn)行全局加載
func init() {
	loaderAbleFactory = NewLoaderAbleFactory()
	loaderAbleFactory.RegisterLoader("phone", &PhoneLoaderAble{})
	loaderAbleFactory.RegisterLoader("car", &CarLoaderAble{})
	log.Println("多態(tài)模型關(guān)系注冊(cè)成功...")
}

六、實(shí)現(xiàn)LoadAble通用的加載函數(shù)

// LoadAble 通用的加載函數(shù),可以處理任何實(shí)現(xiàn)了 LoadableItem 接口的切片
func LoadAble[T LoadAbleItem](items []T) error {
	if len(items) == 0 {
		return nil
	}
 
	// 按類型分組收集ID
	typeIDsMap := make(map[string][]int)
	for _, item := range items {
		typeKey := item.GetAbleType()
		typeIDsMap[typeKey] = append(typeIDsMap[typeKey], item.GetAbleID())
	}
 
	// 使用對(duì)應(yīng)的loader加載數(shù)據(jù)
	typeDataMap := make(map[string]map[int]any)
	for typeName, ids := range typeIDsMap {
		loader, ok := loaderAbleFactory.loaders[typeName]
		if !ok {
			continue
		}
 
		resultMap, err := loader.LoadAble(ids)
		if err != nil {
			return err
		}
		typeDataMap[typeName] = resultMap
	}
 
	// 填充數(shù)據(jù)
	for _, item := range items {
		if dataMap, ok := typeDataMap[item.GetAbleType()]; ok {
			if data, exists := dataMap[item.GetAbleID()]; exists {
				item.SetLoadedAbleData(data)
			}
		}
	}
	return nil
}

七、調(diào)試

  • 準(zhǔn)備數(shù)據(jù)
--orders表
INSERT INTO `orders` (`id`, `order_no`, `orderable_id`, `orderable_type`, `status`, `created_at`, `updated_at`, `deleted_at`) VALUES (1, '202411010001', 1002, 'car', 1, '2024-11-01 12:03:03', '2024-11-01 12:03:06', NULL);
INSERT INTO `orders` (`id`, `order_no`, `orderable_id`, `orderable_type`, `status`, `created_at`, `updated_at`, `deleted_at`) VALUES (2, '202411010002', 1001, 'phone', 1, '2024-11-01 12:03:03', '2024-11-01 12:03:06', NULL);
INSERT INTO `orders` (`id`, `order_no`, `orderable_id`, `orderable_type`, `status`, `created_at`, `updated_at`, `deleted_at`) VALUES (3, '202411010003', 1000, 'car', 1, '2024-11-01 12:03:03', '2024-11-01 12:03:06', NULL);
INSERT INTO `orders` (`id`, `order_no`, `orderable_id`, `orderable_type`, `status`, `created_at`, `updated_at`, `deleted_at`) VALUES (4, '202411010004', 1001, 'car', 1, '2024-11-01 12:03:03', '2024-11-01 12:03:06', NULL);
INSERT INTO `orders` (`id`, `order_no`, `orderable_id`, `orderable_type`, `status`, `created_at`, `updated_at`, `deleted_at`) VALUES (5, '202411010005', 1002, 'phone', 1, '2024-11-01 12:03:03', '2024-11-01 12:03:06', NULL);
 
--phone表
INSERT INTO `phone` (`id`, `phone_name`, `phone_model`, `status`, `created_at`, `updated_at`, `deleted_at`) VALUES (1000, 'XiaoMi', '2S', 2, '2024-11-01 11:59:37', '2024-11-01 11:59:40', NULL);
INSERT INTO `phone` (`id`, `phone_name`, `phone_model`, `status`, `created_at`, `updated_at`, `deleted_at`) VALUES (1001, 'HUAWEI', 'mate60', 1, '2024-11-01 11:59:54', '2024-11-01 11:59:57', NULL);
INSERT INTO `phone` (`id`, `phone_name`, `phone_model`, `status`, `created_at`, `updated_at`, `deleted_at`) VALUES (1002, 'Apple', 'iPhone 12 Pro Max', 1, '2024-11-01 12:00:26', '2024-11-01 12:00:28', NULL);
 
--cars表
INSERT INTO `cars` (`id`, `car_name`, `car_model`, `status`, `created_at`, `updated_at`, `deleted_at`) VALUES (1000, '奧迪', 'A6L', 1, '2024-11-01 11:57:53', '2024-11-01 11:57:55', NULL);
INSERT INTO `cars` (`id`, `car_name`, `car_model`, `status`, `created_at`, `updated_at`, `deleted_at`) VALUES (1001, '寶馬', '5系', 1, '2024-11-01 11:58:12', '2024-11-01 11:58:15', NULL);
INSERT INTO `cars` (`id`, `car_name`, `car_model`, `status`, `created_at`, `updated_at`, `deleted_at`) VALUES (1002, '奔馳', 'E300', 1, '2024-11-01 11:58:53', '2024-11-01 11:58:56', NULL);
  • 編寫代碼
// Gin框架+Gorm為例
api.GET("/orders", controller.GetOrderList)
 
// GetOrderList 獲取訂單列表接口
func GetOrderList(c *gin.Context) {
	orders := make([]*model.Order, 0)
	err := mysql.DefaultMysql.Db.Debug().Find(&orders).Error
	if err != nil {
		c.JSON(200, gin.H{"error": err.Error()})
		return
	}
	err = model.LoadAble(orders)
	if err != nil {
		c.JSON(200, gin.H{"error": err.Error()})
		return
	}
	c.JSON(200, gin.H{"data": orders})
}
  • 發(fā)起請(qǐng)求
curl '127.0.0.1:16888/api/orders'
{
    "data": [
        {
            "id": 1,
            "order_no": "202411010001",
            "orderable_id": 1002,
            "orderable_type": "car",
            "orderable": {
                "id": 1002,
                "car_name": "奔馳",
                "car_model": "E300",
                "status": 1,
                "created_at": "2024-11-01T11:58:53+08:00",
                "updated_at": "2024-11-01T11:58:56+08:00",
                "deleted_at": null
            },
            "status": 1,
            "created_at": "2024-11-01T12:03:03+08:00",
            "updated_at": "2024-11-01T12:03:06+08:00",
            "deleted_at": null
        },
        {
            "id": 2,
            "order_no": "202411010002",
            "orderable_id": 1001,
            "orderable_type": "phone",
            "orderable": {
                "id": 1001,
                "phone_name": "HUAWEI",
                "phone_model": "mate60",
                "status": 1,
                "status_new": 1,
                "created_at": "2024-11-01T11:59:54+08:00",
                "updated_at": "2024-11-01T11:59:57+08:00",
                "deleted_at": null
            },
            "status": 1,
            "created_at": "2024-11-01T12:03:03+08:00",
            "updated_at": "2024-11-01T12:03:06+08:00",
            "deleted_at": null
        },
        {
            "id": 3,
            "order_no": "202411010003",
            "orderable_id": 1000,
            "orderable_type": "car",
            "orderable": {
                "id": 1000,
                "car_name": "奧迪",
                "car_model": "A6L",
                "status": 1,
                "created_at": "2024-11-01T11:57:53+08:00",
                "updated_at": "2024-11-01T11:57:55+08:00",
                "deleted_at": null
            },
            "status": 1,
            "created_at": "2024-11-01T12:03:03+08:00",
            "updated_at": "2024-11-01T12:03:06+08:00",
            "deleted_at": null
        },
        {
            "id": 4,
            "order_no": "202411010004",
            "orderable_id": 1001,
            "orderable_type": "car",
            "orderable": {
                "id": 1001,
                "car_name": "寶馬",
                "car_model": "5系",
                "status": 1,
                "created_at": "2024-11-01T11:58:12+08:00",
                "updated_at": "2024-11-01T11:58:15+08:00",
                "deleted_at": null
            },
            "status": 1,
            "created_at": "2024-11-01T12:03:03+08:00",
            "updated_at": "2024-11-01T12:03:06+08:00",
            "deleted_at": null
        },
        {
            "id": 5,
            "order_no": "202411010005",
            "orderable_id": 1002,
            "orderable_type": "phone",
            "orderable": {
                "id": 1002,
                "phone_name": "Apple",
                "phone_model": "iPhone 12 Pro Max",
                "status": 1,
                "status_new": 1,
                "created_at": "2024-11-01T12:00:26+08:00",
                "updated_at": "2024-11-01T12:00:28+08:00",
                "deleted_at": null
            },
            "status": 1,
            "created_at": "2024-11-01T12:03:03+08:00",
            "updated_at": "2024-11-01T12:03:06+08:00",
            "deleted_at": null
        }
    ]
}

以上就是Golang Gorm實(shí)現(xiàn)自定義多態(tài)模型關(guān)聯(lián)查詢的詳細(xì)內(nèi)容,更多關(guān)于Golang Gorm關(guān)聯(lián)查詢的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!

相關(guān)文章

  • 詳解go語(yǔ)言 make(chan int, 1) 和 make (chan int) 的區(qū)別

    詳解go語(yǔ)言 make(chan int, 1) 和 make (chan int) 的區(qū)別

    這篇文章主要介紹了go語(yǔ)言 make(chan int, 1) 和 make (chan int) 的區(qū)別,本文給大家介紹的非常詳細(xì),具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2020-01-01
  • golang1.23版本之前 Timer Reset方法無(wú)法正確使用

    golang1.23版本之前 Timer Reset方法無(wú)法正確使用

    在Go 1.23之前,使用`time.Reset`函數(shù)時(shí)需要先調(diào)用`Stop`并明確從timer的channel中抽取出東西,以避免潛在的問(wèn)題,然而,這在實(shí)際代碼中難以實(shí)現(xiàn),因?yàn)樵O(shè)置定時(shí)器狀態(tài)和發(fā)送channel的操作并不是原子的,在某些情況下,這會(huì)導(dǎo)致timer在不應(yīng)該觸發(fā)時(shí)提前觸發(fā)
    2025-01-01
  • Golang實(shí)現(xiàn)AES對(duì)稱加密算法實(shí)例詳解

    Golang實(shí)現(xiàn)AES對(duì)稱加密算法實(shí)例詳解

    所謂對(duì)稱加密是指在加密和解碼時(shí)使用同一密鑰的加密方式,下面這篇文章主要給大家介紹了關(guān)于Golang實(shí)現(xiàn)AES對(duì)稱加密算法的相關(guān)資料,文中通過(guò)實(shí)例代碼介紹的非常詳細(xì),需要的朋友可以參考下
    2023-02-02
  • Go語(yǔ)言錯(cuò)誤處理異常捕獲+異常拋出

    Go語(yǔ)言錯(cuò)誤處理異常捕獲+異常拋出

    這篇文章主要介紹了Go語(yǔ)言錯(cuò)誤處理異常捕獲和異常拋出,Go語(yǔ)言的作者認(rèn)為java等語(yǔ)言的錯(cuò)誤處理底層實(shí)現(xiàn)較為復(fù)雜,就實(shí)現(xiàn)了函數(shù)可以返回錯(cuò)誤類型以及簡(jiǎn)單的異常捕獲,雖然簡(jiǎn)單但是也非常精妙,大大的提高了運(yùn)行效率,下文需要的朋友可以參考一下
    2022-02-02
  • Golang并發(fā)編程之Channel詳解

    Golang并發(fā)編程之Channel詳解

    傳統(tǒng)的并發(fā)編程模型是基于線程和共享內(nèi)存的同步訪問(wèn)控制的,共享數(shù)據(jù)受鎖的保護(hù),使用線程安全的數(shù)據(jù)結(jié)構(gòu)會(huì)使得這更加容易。本文將詳細(xì)介紹Golang并發(fā)編程中的Channel,,需要的朋友可以參考下
    2023-05-05
  • Go語(yǔ)言利用ssh連接服務(wù)器的方法步驟

    Go語(yǔ)言利用ssh連接服務(wù)器的方法步驟

    這篇文章主要介紹了Go語(yǔ)言利用ssh連接服務(wù)器的方法步驟,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2021-04-04
  • Go語(yǔ)言Mock使用基本指南詳解

    Go語(yǔ)言Mock使用基本指南詳解

    這篇文章主要介紹了Go語(yǔ)言Mock使用基本指南詳解,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2020-06-06
  • gRPC超時(shí)攔截器實(shí)現(xiàn)示例

    gRPC超時(shí)攔截器實(shí)現(xiàn)示例

    這篇文章主要為大家介紹了gRPC超時(shí)攔截器實(shí)現(xiàn)示例,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2022-06-06
  • PHP結(jié)構(gòu)型模式之組合模式

    PHP結(jié)構(gòu)型模式之組合模式

    這篇文章主要介紹了PHP組合模式Composite Pattern優(yōu)點(diǎn)與實(shí)現(xiàn),組合模式是一種結(jié)構(gòu)型模式,它允許你將對(duì)象組合成樹形結(jié)構(gòu)來(lái)表示“部分-整體”的層次關(guān)系。組合能讓客戶端以一致的方式處理個(gè)別對(duì)象和對(duì)象組合
    2023-04-04
  • 簡(jiǎn)單聊聊Go?for?range中容易踩的坑

    簡(jiǎn)單聊聊Go?for?range中容易踩的坑

    for循環(huán)問(wèn)題,在面試中經(jīng)常都會(huì)被問(wèn)到,并且在實(shí)際業(yè)務(wù)項(xiàng)目中也經(jīng)常用到for循環(huán),要是沒(méi)用好,一不下心就掉坑,本文就來(lái)講講Go?for?range中容易踩的坑吧
    2023-03-03

最新評(píng)論