How to Set Up MySQL Database Connection Using GORM in Gorig

Gorig provides a zero-configuration-boilerplate approach to MySQL connectivity by encapsulating GORM initialization in the gormt utility and automatically wiring connections through the domainx service layer.

The Gorig framework abstracts database lifecycle management into a declarative configuration system. By defining MySQL parameters in YAML and enabling the GormInit flag, the framework handles driver creation, connection pooling, read-write splitting, and custom logging automatically through its internal utils/gormt and domainx packages.

Configuration Structure

All MySQL connection parameters reside in a YAML configuration file (conventionally gorm_v2.yml) loaded via utils/cofigure. The framework expects a specific hierarchy under the Mysql key:

Mysql:
  primary:
    GormInit: 1               # Required: enables GORM initialization on startup

    IsOpenReadDb: 1           # Optional: enables read-write splitting (1=enabled)

    Write:
      Host: 127.0.0.1
      Port: 3306
      User: root
      Pass: your_password
      DataBase: myapp
      Charset: utf8mb4
    Read:
      Host: 127.0.0.1
      Port: 3307
      User: read_user
      Pass: read_pwd
      DataBase: myapp
      Charset: utf8mb4

The utils/cofigure/cfg.go loader parses these keys and makes them available to the GORM builder. Each named connection (e.g., primary) becomes a distinct database instance within the application.

How Gorig Initializes MySQL Connections

The framework follows a three-phase initialization pattern: service registration, driver construction, and startup execution.

Service Registration

In domainx/db.gormb.go, the MySQL service registers itself during package initialization (lines 23-27):

func init() {
    RegisterDBService(Mysql, GormDBServ)
}

This registration maps the Mysql constant (defined in domainx/cont.go) to the GormDBServ implementation, allowing the framework to route MySQL-specific startup logic through the generic service interface.

Driver Construction

The utils/gormt/client.go file contains the core GORM initialization logic. The GetOneMysqlClient function (lines 18-23) retrieves the write DSN and delegates to GetSqlDriver:

func GetOneMysqlClient(name string) (*gorm.DB, error) {
    dsn := getDsn(name, "Write")
    return GetSqlDriver(dsn, name)
}

The GetSqlDriver function (lines 25-34) opens the database connection:

func GetSqlDriver(dsn string, name string) (*gorm.DB, error) {
    dialector := getDbDialector(dsn)
    db, err := gorm.Open(dialector, &gorm.Config{})
    // ... error handling and read replica setup
}

If IsOpenReadDb equals 1, the framework registers a read-replica resolver (lines 53-60) using GORM's dbresolver plugin, routing read-only queries to the configured replica while writes target the primary.

Startup Sequence

When the application boots via bootstrap/startup.go, the StartUp() function triggers serv.Running(), which executes the Start method in domainx/db.gormb.go (lines 44-52). This method scans the Mysql configuration subtree and, for every entry with GormInit: 1, calls initMysqlDB.

The initMysqlDB function (lines 93-101) invokes gormt.GetOneMysqlClient for each named database and stores the resulting *gorm.DB instance in gormDbMysqlMap, making it available for request-scoped retrieval.

Using MySQL in Your Application Code

Once initialized, Gorig provides two primary patterns for accessing MySQL connections: through the request context or via direct lookup.

Accessing DB via Context

The domainx.Con struct (request-level context) includes a MysqlDB *gorm.DB field. When a request passes through the domainx middleware (handled in domainx/api.go), the framework attaches the appropriate database connection to the context:

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

func GetUser(c *gin.Context) {
    con := domainx.NewCon(c) // Context wrapper created by middleware
    
    var user User
    err := con.MysqlDB.WithContext(c.Request.Context()).
        Table("users").
        Where("id = ?", c.Param("id")).
        First(&user).Error
    
    if err != nil {
        c.JSON(500, gin.H{"error": err.Error()})
        return
    }
    c.JSON(200, user)
}

Direct DB Access by Name

For background tasks or non-request contexts, retrieve the connection directly by its configuration name:

db := domainx.UseDbConn("primary")
if db == nil {
    panic("MySQL connection not initialized")
}

var count int64
db.Table("users").Count(&count)
fmt.Println("Total users:", count)

The UseDbConn function queries the gormDbMysqlMap populated during initMysqlDB, returning the cached *gorm.DB instance.

Advanced Features

Read-Write Splitting

When IsOpenReadDb is enabled in the YAML configuration, Gorig automatically configures GORM's dbresolver plugin. The implementation in utils/gormt/client.go (lines 53-60) registers the read DSN as a replica source:

if isOpenReadDb == 1 {
    db.Use(dbresolver.Register(dbresolver.Config{
        Sources:  []gorm.Dialector{getDbDialector(dsn)},
        Replicas: []gorm.Dialector{getDbDialector(readDsn)},
        Policy:   dbresolver.RandomPolicy{},
    }))
}

This configuration routes SELECT queries to the read replica while INSERT, UPDATE, and DELETE operations target the write database.

Custom Logging

Gorig replaces GORM's default logger with a custom implementation via the redefineLog function (lines 68-73 in client.go). This integrates GORM's SQL logging with the framework's centralized logging system, ensuring consistent log formatting and output destinations across the application.

Summary

  • Configuration-driven setup: Define MySQL connections in gorm_v2.yml with Mysql.<name> keys and set GormInit: 1 to enable automatic initialization.
  • Automatic service wiring: The domainx package registers MySQL as a core service during init(), while bootstrap.StartUp() triggers connection establishment at runtime.
  • GORM abstraction: The utils/gormt/client.go module handles DSN generation, dialector creation, and GORM session management, including optional read-write splitting via dbresolver.
  • Dual access patterns: Retrieve connections either through the request-scoped domainx.Con.MysqlDB field or directly via domainx.UseDbConn("<name>").
  • Zero boilerplate: Once configured, the framework manages connection pooling, logging integration, and lifecycle management without additional application code.

Frequently Asked Questions

How do I configure multiple MySQL databases in Gorig?

Add multiple entries under the Mysql key in your YAML configuration, each with a unique name (e.g., primary, analytics). Ensure each has GormInit: 1 set. The framework initializes all marked databases during startup and stores them in gormDbMysqlMap, accessible via domainx.UseDbConn("analytics").

Where does Gorig handle connection pooling for MySQL?

Connection pooling is managed internally by GORM's underlying database/sql driver, configured through the DSN parameters generated in utils/gormt/client.go. While Gorig doesn't expose explicit pool configuration in the YAML, you can customize GORM's ConnPool or driver settings by modifying the gorm.Config passed to gorm.Open in the GetSqlDriver function.

How do I enable debug logging for SQL queries in Gorig?

Gorig automatically replaces GORM's default logger with a custom implementation (redefineLog in utils/gormt/client.go, lines 68-73) that integrates with the framework's logging system. To adjust log levels or output formats, modify the redefineLog function or configure the framework's global logger, as GORM's SQL output flows through this custom adapter.

Can I use Gorig's MySQL setup without the request context?

Yes. While the domainx.Con struct provides request-scoped access via MysqlDB, you can retrieve the underlying *gorm.DB instance directly using domainx.UseDbConn("<name>"). This returns the singleton connection from gormDbMysqlMap initialized at startup, suitable for background workers, scheduled tasks, or CLI tools that operate outside the HTTP request lifecycle.

Have a question about this repo?

These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →