Skip to content

1saifj/gorm_multipe_schemas

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

7 Commits
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Introduction

Gorm is an exceptional Object-Relational Mapping (ORM) library for Golang, equipped with a wide range of features.

Identifying the Issue

Although the Gorm documentation is comprehensive, it does not always include all the minor details that a developer might need. I encountered a specific problem where I needed to manage two schemas with one database, as illustrated below. The aim was to maintain a schema of APP and another schema of AUTH within the same database. This separation can be useful for breaking down the application into smaller services or for managing the app database from a different viewpoint.

image

Upon reading the Gorm documentation, I did not find a direct solution to my problem. However, by exploring the Gorm source code, I was able to devise a solution.

The Solution

To enable Gorm to manage multiple schemas within one database, we can use table naming for each table model we create.

type TablerWithNamer interface {
	TableName(Namer) string
}

Here, TableName is an interface used to modify the given name for a table. To employ this function, we need to define a custom struct that implements this interface.

// CustomTabler is a custom struct that implements TablerWithNamer
type CustomTabler struct {
	gorm.Tabler
}
// TableName returns the custom table name based on the struct name
func (ct *CustomTabler) TableName() string {
	// Generate and return the custom table name based on your logic
	// Example: return "custom_table_name"
	return "custom_table_name"
}

Now let's implement our database schemas as per the diagram above, using a full code example that utilizes Gorm's table renaming, scopes, and clauses.

package main
 
import (
	"fmt"
	"gorm.io/driver/postgres"
	"gorm.io/gorm"
	"gorm.io/gorm/clause"
)
 
const (
	AppSchema  = "app"
	AuthSchema = "auth"
)
 
// User is a model representing the users table
type User struct {
	ID   uint
	Name string
}
 
// TableName returns the custom table name for the User model
func (User) TableName() string {
	return AuthSchema + ".user"
}
 
// Order is a model representing the orders table
type Order struct {
	ID     uint
	Name   string
	UserID uint
}
 
// TableName returns the custom table name for the Order model
func (Order) TableName() string {
	return AppSchema + ".order"
}
 
func main() {
	// Connect to the database
	db, err := gorm.Open(postgres.Open("host=localhost user=postgres password=postgres dbname=postgres port=5432 sslmode=disable TimeZone=Asia/Jakarta"), &gorm.Config{})
	if err != nil {
		panic(err)
	}
 
	// Create schema if not exist
	db.Exec("CREATE SCHEMA IF NOT EXISTS " + AppSchema)
	db.Exec("CREATE SCHEMA IF NOT EXISTS " + AuthSchema)
 
	// Auto-migrate the models
	err = db.AutoMigrate(&User{}, &Order{})
	if err != nil {
		panic(err)
	}
 
	// Create a new user in the auth schema
	user := User{Name: "John"}
	db.Create(&user)
 
	// Create a new order associated with the user in the app schema
	order := Order{Name: "Order 1", UserID: user.ID}
	db.Create(&order)
 
	// Fetch all users from the auth schema
	var authUsers []User
	db.Find(&authUsers)
	fmt.Println("Auth Users:", authUsers)
 
	// Fetch all orders from the app schema
	var appOrders []Order
	db.Find(&appOrders)
	fmt.Println("App Orders:", appOrders)
 
	// Fetch all orders from the app schema with the associated user
	var appOrdersWithUser []Order
	db.Preload(clause.Associations).Find(&appOrdersWithUser)
	fmt.Println("App Orders with User:", appOrdersWithUser)
}

We begin by creating our models, such as the user and order models. We establish a database connection and ensure our database includes these schemas, creating them if necessary. clause.Associations are used to specify associations to be preloaded or eager-loaded when querying the database. It allows you to load related associations in a single query to minimize the number of database round-trips and improve performance.

About

An example how to use gorm to handle multiple schemas with one database.

Topics

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Languages