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 的透明分片特性使得你可以像操作单个数据库一样操作分布式数据库集群,从而大大简化了分库分表带来的复杂性。

相关推荐
CHHC18804 小时前
golang 使用gzip对json例子
开发语言·golang·json
程序猿-瑞瑞4 小时前
22 go语言(golang) - gin框架安装及使用(三)
开发语言·golang·gin
终生成长者4 小时前
go 自己写序列化函数不转义
java·开发语言·golang
LuckyLay5 小时前
Golang学习笔记_08——For循环
笔记·学习·golang
LuckyLay5 小时前
Golang学习笔记_13——数组
笔记·学习·golang·数组·array
码出钞能力5 小时前
对golang的io型进程进行off-cpu分析
开发语言·golang
Generalzy10 小时前
golang操作sqlite3加速本地结构化数据查询
jvm·golang·sqlite
Xvens10 小时前
Golang Gin Redis+Mysql 同步查询更新删除操作(我的小GO笔记)
redis·golang·gin
明月看潮生10 小时前
青少年编程与数学 02-004 Go语言Web编程 07课题、WebSockets
开发语言·青少年编程·golang·编程与数学