Skip to content

Latest commit

 

History

History

fxorm

Folders and files

NameName
Last commit message
Last commit date

parent directory

..
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Fx ORM Module

ci go report codecov Deps PkgGoDev

Fx module for orm.

Installation

go get github.com/ankorstore/yokai/fxorm

Documentation

Dependencies

This module is intended to be used alongside:

Loading

To load the module in your Fx application:

package main

import (
	"github.com/ankorstore/yokai/fxconfig"
	"github.com/ankorstore/yokai/fxlog"
	"github.com/ankorstore/yokai/fxorm"
	"github.com/ankorstore/yokai/fxtrace"
	"go.uber.org/fx"
	"gorm.io/gorm"
)

type Model struct {
	Name string
}

func main() {
	fx.New(
		fxconfig.FxConfigModule,          // load the module dependencies
		fxlog.FxLogModule,
		fxtrace.FxTraceModule,
		fxorm.FxOrmModule,                // load the module
		fx.Invoke(func(gormDB *gorm.DB) { // invoke the orm
			gormDB.Create(&Model{Name: "some name"})
		}),
	).Run()
}

Configuration

This module provides the possibility to configure the ORM driver:

  • sqlite for SQLite databases
  • mysql for MySQL databases
  • postgres for PostgreSQL databases
  • sqlserver for SQL Server databases

You can also provide to the ORM the databasedsn, some config, and configure SQL queries logging and tracing.

# ./configs/config.yaml
app:
  name: app
  env: dev
  version: 0.1.0
  debug: false
modules:
  orm:
    driver: mysql                                               # driver to use
    dsn: "user:password@tcp(localhost:3306)/db?parseTime=True"  # database DSN to use
    config:
      dry_run: false                                            # disabled by default
      skip_default_transaction: false                           # disabled by default
      full_save_associations: false                             # disabled by default
      prepare_stmt: false                                       # disabled by default
      disable_automatic_ping: false                             # disabled by default
      disable_foreign_key_constraint_when_migrating: false      # disabled by default
      ignore_relationships_when_migrating: false                # disabled by default
      disable_nested_transaction: false                         # disabled by default
      allow_global_update: false                                # disabled by default
      query_fields: false                                       # disabled by default
      translate_error: false                                    # disabled by default
    log:
      enabled: true  # to log SQL queries, disabled by default
      level: info    # with a minimal level
      values: true   # by adding or not clear SQL queries parameters values in logs, disabled by default
    trace:
      enabled: true  # to trace SQL queries, disabled by default
      values: true   # by adding or not clear SQL queries parameters values in trace spans, disabled by default

See GORM Config for more details about the modules.orm.config configuration keys.

For security reasons, you should avoid to hardcode DSN sensible parts (like the password) in your config files, you can use the env vars placeholders instead:

# ./configs/config.yaml
modules:
  orm:
    driver: mysql
    dsn: "${MYSQL_USER}:${MYSQL_PASSWORD}@tcp(${MYSQL_HOST}:${MYSQL_PORT})/${MYSQL_DATABASE}?parseTime=True"

Auto migrations

This module provides the possibility to run automatically your schemas migrations with RunFxOrmAutoMigrate():

package main

import (
	"github.com/ankorstore/yokai/fxconfig"
	"github.com/ankorstore/yokai/fxlog"
	"github.com/ankorstore/yokai/fxorm"
	"github.com/ankorstore/yokai/fxtrace"
	"go.uber.org/fx"
	"gorm.io/gorm"
)

type Model struct {
	Name string
}

func main() {
	fx.New(
		fxconfig.FxConfigModule,             // load the module dependencies
		fxlog.FxLogModule,
		fxtrace.FxTraceModule,
		fxorm.FxOrmModule,                   // load the module
		fxorm.RunFxOrmAutoMigrate(&Model{}), // run auto migration for Model
		fx.Invoke(func(gormDB *gorm.DB) {        // invoke the orm
			gormDB.Create(&Model{Name: "some name"})
		}),
	).Run()
}

Performance

See GORM performance recommendations.

Disable Default Transaction

Gorm performs write (create/update/delete) operations by default inside a transaction to ensure data consistency, which is not optimized for performance.

You can disable it in the configuration:

# ./configs/config.yaml

modules:
  orm:
    config:
      skip_default_transaction: true # disable default transaction

Cache Prepared Statement

To create a prepared statement when executing any SQL (and cache them to speed up future calls):

# ./configs/config.yaml
modules:
  orm:
    config:
      prepare_stmt: true # enable prepared statements

Override

By default, the gorm.DB is created by the DefaultOrmFactory.

If needed, you can provide your own factory and override the module:

package main

import (
	"github.com/ankorstore/yokai/fxconfig"
	"github.com/ankorstore/yokai/fxlog"
	"github.com/ankorstore/yokai/fxorm"
	"github.com/ankorstore/yokai/fxtrace"
	"github.com/ankorstore/yokai/orm"
	"go.uber.org/fx"
	"gorm.io/gorm"
)

type CustomOrmFactory struct{}

func NewCustomOrmFactory() orm.OrmFactory {
	return &CustomOrmFactory{}
}

func (f *CustomOrmFactory) Create(options ...orm.OrmOption) (*gorm.DB, error) {
	return &gorm.DB{...}, nil
}

type Model struct {
	Name string
}

func main() {
	fx.New(
		fxconfig.FxConfigModule,            // load the module dependencies
		fxlog.FxLogModule,
		fxtrace.FxTraceModule,
		fxorm.FxOrmModule,                  // load the module
		fx.Decorate(NewCustomOrmFactory),   // override the module with a custom factory
		fx.Invoke(func(customDb *gorm.DB) { // invoke the custom ORM
			customDb.Create(&Model{Name: "custom"})
		}),
	).Run()
}