In order to support replication, I decided to divide the DB endpoint by Read / Write. I examined how to handle it with Go / Gorm2.
Each Method of Gorm is wrapped in a Type that has multiple Connections for each Endpoint. By doing this, the side using the connection can operate the DB without being aware of the endpoint.
db/connect.go
package db
import (
"os"
"gorm.io/driver/mysql"
"gorm.io/gorm"
)
type SqlHandler struct {
ReadConn *gorm.DB
WriteConn *gorm.DB
}
func Connect() *SqlHandler {
readConn, err := gorm.Open(GetDBConfig("read"))
if err != nil {
panic(err.Error())
}
writeConn, err := gorm.Open(GetDBConfig("write"))
if err != nil {
panic(err.Error())
}
sqlHandler := SqlHandler{
ReadConn: readConn,
WriteConn: writeConn,
}
return &sqlHandler
}
func GetDBConfig(endpoint string) (gorm.Dialector, *gorm.Config) {
USER := "myUser"
PASS := "hoge1234"
PROTOCOL := "tcp(" + endpoint + ":5050)"
DBNAME := "myDB"
OPTION := "charset=utf8&parseTime=True&loc=Local"
mysqlConfig := mysql.Config{
DSN: USER + ":" + PASS + "@" + PROTOCOL + "/" + DBNAME + "?" + OPTION,
}
config := &gorm.Config{}
return mysql.New(mysqlConfig), config
}
func (handler *SqlHandler) Find(out interface{}, where ...interface{}) *gorm.DB {
return handler.ReadConn.Find(out, where...)
}
func (handler *SqlHandler) Exec(sql string, values ...interface{}) *gorm.DB {
return handler.WriteConn.Exec(sql, values...)
}
func (handler *SqlHandler) First(out interface{}, where ...interface{}) *gorm.DB {
return handler.ReadConn.Find(out, where...)
}
func (handler *SqlHandler) Raw(sql string, values ...interface{}) *gorm.DB {
return handler.WriteConn.Raw(sql, values...)
}
func (handler *SqlHandler) Create(value interface{}) *gorm.DB {
return handler.WriteConn.Create(value)
}
func (handler *SqlHandler) Save(value interface{}) *gorm.DB {
return handler.WriteConn.Save(value)
}
func (handler *SqlHandler) Delete(value interface{}) *gorm.DB {
return handler.WriteConn.Delete(value)
}
func (handler *SqlHandler) Where(query interface{}, args ...interface{}) *gorm.DB {
return handler.WriteConn.Where(query, args...)
}
Replication (https://ja.wikipedia.org/wiki/%E3%83%AC%E3%83%97%E3%83%AA%E3%82%B1%E3%83%BC%E3%82 % B7% E3% 83% A7% E3% 83% B3)
For the parts that can be issued by query itself, such as func Exec
and func Raw
, there is a possibility of both read / write, and I am wondering which one to distribute.
This time, I assigned it to write. As much as possible, users want to be able to use it without being aware of endpoints ...
I have decided to use CQRS, and I feel that SQL solid writing is likely to increase in the first place. The meaning of using Gorm is a little diminished, but I would like it when considering the mapping to Type as an ORM. I think it would be good to make only the mapping part by yourself! !!
-Golang --Building Clean Architecture API with Echo and GORM
Recommended Posts