ShardingSphere-Proxy 连接实战:从 Golang 原生 SQL 到 GORM 的应用

在这篇文章《ShardingSphereProxy:快速入门》中,我们介绍了如何通过 Navicat 连接 ShardingSphere-Proxy。

实际上,ShardingSphere-Proxy 兼容标准的 SQL 和原生数据库协议,因此你可以使用任何 MySQL 客户端与其进行连接,包括 Golang 的原生 SQL 库和流行的 ORM 框架 GORM。

接下来,我们将展示如何使用 Golang 原生 SQL 和 GORM 连接并操作 ShardingSphere-Proxy。

使用 Golang 原生 SQL 连接 ShardingSphere-Proxy

话不多少,我们直接上示例。

基于我们的测试实例。

由于 Proxy 运行在 Docker 容器上,并且暴露了端口 13308,使用以下连接信息:

主机:localhost 或 Docker 容器的 IP 地址

端口:13308

用户名:root 或 sharding(根据我们在 global.yaml 中的配置)

密码:对应的密码

以下是使用 Golang 原生 SQL 连接 ShardingSphere-Proxy 的示例代码:

Go 复制代码
package main

import (
	"database/sql"
	"fmt"
	"log"

	_ "github.com/go-sql-driver/mysql"
)

func main() {
	// ShardingSphere Proxy的连接字符串
	dsn := "sharding:sharding@tcp(localhost:13308)/sharding"

	// 打开数据库连接
	db, err := sql.Open("mysql", dsn)
	if err != nil {
		log.Fatal(err)
	}
	defer db.Close()

	// 验证连接
	err = db.Ping()
	if err != nil {
		log.Fatal(err)
	}

	fmt.Println("Successfully connected to ShardingSphere Proxy!")

	// 执行查询(示例)
	rows, err := db.Query("SELECT * FROM orders LIMIT 10")
	if err != nil {
		log.Fatal(err)
	}
	defer rows.Close()

	// 处理查询结果
	for rows.Next() {
		var column1 int64
		var column2 string
		var column3 int
		var column4 int
		var column5 string
		// 根据你的表结构调整字段类型和数量
		err := rows.Scan(&column1, &column2, &column3, &column4, &column5)
		if err != nil {
			log.Fatal(err)
		}
		fmt.Printf("Column1: %s, Column2: %d\n", column1, column2)
	}
	// 检查是否有错误发生
	if err = rows.Err(); err != nil {
		log.Fatal(err)
	}
}

使用 GORM 连接并操作 ShardingSphere-Proxy

GORM 是一个流行的 Golang ORM 框架,它使得数据库操作更加简洁和高效。以下是如何使用 GORM 连接 ShardingSphere-Proxy 并进行基本操作的示例:

Go 复制代码
package main

import (
	"fmt"
	"math/rand"
	"time"

	"github.com/bwmarrin/snowflake"
	"gorm.io/driver/mysql"
	"gorm.io/gorm"
	"gorm.io/gorm/logger"
)

var globalDB *gorm.DB

type Order struct {
	ID        int64  `gorm:"primaryKey"`
	OrderId   string `gorm:"sharding:order_id"` // 指明 OrderId 是分片键
	UserID    int64  `gorm:"sharding:user_id"`
	ProductID int64
	OrderDate int64
}

type Product struct {
	ID   int64  `gorm:"primaryKey"`
	Name string `gorm:"name"`
}

// 定义结构体,用于接收查询结果
type OrderGroup struct {
	ID         int64  `gorm:"primaryKey"`
	OrderId    string `gorm:"sharding:order_id"` // 指明 OrderId 是分片键
	UserID     int64  `gorm:"sharding:user_id"`
	ProductID  int64
	OrderDate  int64
	SumProduct int64
	MaxProduct int64
}

type OrderProduct struct {
	Order
	Product
}

type User struct {
	ID   int64  `gorm:"primaryKey"`
	Name string `gorm:"name"`
}

type OrderUser struct {
	Order
	User
}

func main() {
	InitDb()
    // 示例:插入订单数据
	InsertRandomOrders()
    // 场景1:全表查询,不含分表键
	FindAllOrders()
}
// 随机生成一些订单数据插入
func InsertRandomOrders() {
	node, err := snowflake.NewNode(1)
	if err != nil {
		fmt.Println("Error creating snowflake node:", err)
		return
	}

	now := time.Now()
	for i := 0; i < 10; i++ {
		// 雪花id生成
		// 生成一个ID
		id := node.Generate()
		order := Order{
			ID:        id.Int64(),
			OrderId:   fmt.Sprintf("20240101ORDER%04d", rand.Int31n(10000)),
			UserID:    int64(rand.Int31n(10000)),
			ProductID: int64(rand.Int31n(1000)),
			OrderDate: now.Unix(),
		}
		InsertOrder(order)
	}
	// orderDate 用2025年,拼接当前月,日,时,分秒
	orderDate := time.Date(2025, now.Month(), now.Day(), now.Hour(), now.Minute(), now.Second(), 0, time.UTC)
	for i := 0; i < 10; i++ {
		id := node.Generate()
		order := Order{
			ID:        id.Int64(),
			OrderId:   fmt.Sprintf("20250101ORDER%04d", rand.Int31n(10000)),
			UserID:    int64(rand.Int31n(10000)),
			ProductID: int64(rand.Int31n(1000)),
			OrderDate: orderDate.Unix(),
		}
		InsertOrder(order)
	}
}

// 插入订单数据
func InsertOrder(order Order) error {
	err := globalDB.Create(&order).Error
	if err != nil {
		fmt.Println("Error creating order:", err)
	}
	return nil
}

// 场景1:全表查询,不含分表键
func FindAllOrders() ([]Order, error) {
	var orders []Order
	err := globalDB.Table("orders").Find(&orders).Error
	if err != nil {
		fmt.Println("Error finding orders:", err)
		return nil, err
	}
	fmt.Println("场景1:全表查询,不含分表键 orders:", orders)
	return orders, err
}
// InitDb 初始化数据库连接
func InitDb() *gorm.DB {
	log := logger.Default.LogMode(logger.Info)
	// 连接到 MySQL 数据库
	dsn := "sharding:sharding@tcp(localhost:13308)/sharding"
	db, err := gorm.Open(mysql.New(mysql.Config{
		DSN: dsn,
	}), &gorm.Config{
		Logger: log,
	})
	if err != nil {
		panic("failed to connect database")
	}
	globalDB = db
	return db
}

通过这两个示例,你可以看到使用 Golang 原生 SQL 和 GORM 连接并操作 ShardingSphere-Proxy 是非常简单和直观的。ShardingSphere-Proxy 的透明分片特性使得你可以像操作单个数据库一样操作分布式数据库集群,从而大大简化了分库分表带来的复杂性。

相关推荐
不知名美食探索家4 小时前
【11】Redis快速安装与Golang实战指南
redis·golang·bootstrap
普通网友4 小时前
内置AI与浏览器的开源终端Wave Terminal安装与远程连接内网服务器教程
开发语言·后端·golang
行思理5 小时前
go语言应该如何学习
开发语言·学习·golang
returnShitBoy5 小时前
Go语言中的垃圾回收是如何工作的?
java·jvm·golang
普通网友6 小时前
如何在CentOS部署青龙面板并实现无公网IP远程访问本地面板
开发语言·后端·golang
LuckyLay11 小时前
LeetCode算法题(Go语言实现)_38
算法·leetcode·golang
二狗哈15 小时前
go游戏后端开发31:麻将游戏的碰牌与胡牌逻辑
服务器·游戏·golang
dg101118 小时前
go-zero学习笔记(六)---gozero中间件介绍
笔记·学习·golang
q567315231 天前
使用Alamofire下载网站首页内容
开发语言·爬虫·python·scrapy·golang
小诸葛的博客1 天前
Go 语言中的select是做什么的
数据库·sql·golang