这是《Golang GORM实战》系列的第二篇,在这篇文章中我们来了解一下GORM是如何连接不同类型的数据库,以及如何配置连接时的参数。
连接数据库
使用GORM连接数据库还是比较简单的,概括起来就是以下三个步骤:
gorm.io/gormgorm.io/driver/sqlite
通过上述三个步骤,最终获取一个gorm.DB对象,我们便可以使用该对象的方法操作数据库,如Create,Delete等方法。
下面我们来看MySQL,PostgreSQL,SQLite,SQL Server等不同数据库是怎么执行上述几个步骤连接数据库的:
简单连接
下面是连接mysql数据库最简单的方式,我们只需要定义好dsn便可以了,如下:
import (
"gorm.io/driver/mysql"
"gorm.io/gorm"
)
func main() {
dsn := "user:pass@tcp(127.0.0.1:3306)/dbname?charset=utf8mb4&parseTime=True&loc=Local"
db, err := gorm.Open(mysql.Open(dsn))
}
mysql.New
如果我们在连接数据库时,想进一步配置,则可以使用mysql.New()函数,该函数可以传递一个mysql.Config进行详细配置,如:
dsn := "root:123456@tcp(127.0.0.1:3306)/test?charset=utf8mb4&parseTime=true&loc=UTC"
db, err := gorm.Open(mysql.New(mysql.Config{
DSN: dsn, // DSN data source name
DefaultStringSize: 256, // string 类型字段的默认长度
DisableDatetimePrecision: true, // 禁用 datetime 精度,MySQL 5.6 之前的数据库不支持
DontSupportRenameIndex: true, // 重命名索引时采用删除并新建的方式,MySQL 5.7 之前的数据库和 MariaDB 不支持重命名索引
DontSupportRenameColumn: true, // 用 `change` 重命名列,MySQL 8 之前的数据库和 MariaDB 不支持重命名列
SkipInitializeWithVersion: false, // 根据当前 MySQL 版本自动配置
}))
如果我们查看mysql.Config,可以更加了解在连接数据库时,还可以配置哪些参数,mysql.Config的源码如下:
type Config struct {
DriverName string
DSN string
Conn gorm.ConnPool
SkipInitializeWithVersion bool
DefaultStringSize uint
DefaultDatetimePrecision *int
DisableDatetimePrecision bool
DontSupportRenameIndex bool
DontSupportRenameColumn bool
DontSupportForShareClause bool
}
通过sql.DB初始化*gorm.DB
如果我们自己使用database/sql打开一个数据库连接,那么也可以利用这个已经存在的连接,来初始化一个gorm.DB对象, 如:
package main
import (
"database/sql"
"gorm.io/driver/mysql"
"gorm.io/gorm"
)
func main() {
db, _ := sql.Open("mysql", "root:123456@tcp(localhost:3306)/test?charset=utf8&parseTime=True&loc=Local")
db,err := gorm.Open(mysql.New(mysql.Config{
Conn: db,
}))
}
PostgreSQL
简单连接
import (
"gorm.io/driver/postgres"//驱动库
"gorm.io/gorm"
)
dsn := "host=localhost user=gorm password=gorm dbname=gorm port=9920 sslmode=disable TimeZone=Asia/Shanghai"
db, err := gorm.Open(postgres.Open(dsn))
postgres.New
package main
import (
"gorm.io/driver/postgres"
"gorm.io/gorm"
)
func main() {
dsn := "host=localhost user=gorm password=gorm dbname=gorm port=9920 sslmode=disable TimeZone=Asia/Shanghai"
db, err := gorm.Open(postgres.New(postgres.Config{
DSN: dsn,
PreferSimpleProtocol: true,
}))
}
通过sql.DB初始化*gorm.DB
package main
import (
"database/sql"
"gorm.io/driver/postgres"
"gorm.io/gorm"
)
func main() {
dsn := "host=localhost user=gorm password=gorm dbname=gorm port=9920 sslmode=disable TimeZone=Asia/Shanghai"
sqlDB, _ := sql.Open("pgx", dsn)
db, err := gorm.Open(postgres.New(postgres.Config{
Conn: sqlDB,
PreferSimpleProtocol: true,
}))
}
SQL Server
简单连接
import (
"gorm.io/driver/sqlserver"
"gorm.io/gorm"
)
dsn := "sqlserver://gorm:LoremIpsum86@localhost:9930?database=gorm"
db, err := gorm.Open(sqlserver.Open(dsn))
sqlserver.New
package main
import (
"gorm.io/driver/sqlserver"
"gorm.io/gorm"
)
func main() {
dsn := "sqlserver://gorm:LoremIpsum86@localhost:9930?database=gorm"
db, err := gorm.Open(sqlserver.New(sqlserver.Config{
DSN: dsn,
}))
}
通过sql.DB初始化*gorm.DB
package main
import (
"database/sql"
"gorm.io/driver/sqlserver"
"gorm.io/gorm"
)
func main() {
dsn := "sqlserver://gorm:LoremIpsum86@localhost:9930?database=gorm"
sqlDB, _ := sql.Open("sqlserver", dsn)
db, err := gorm.Open(sqlserver.New(sqlserver.Config{
Conn: sqlDB,
}))
}
SQLite
因为SQLite数据库其实只是一个文件而已,所以SQLite的连接非常简单,只需要传入SQLite数据库的文件路径即可,比如我们连接一个在当前目录的gorm.db数据,其连接方式如下:
import (
"gorm.io/driver/sqlite" //驱动库
"gorm.io/gorm"
)
db, err := gorm.Open(sqlite.Open("gorm.db"))
另外,连接SQLite数据库时,也可以在内存中创建临时数据库,而需要一个实际的数据库,其连接方式如下所示:
db, err := gorm.Open(sqlite.Open("file::memory:?cache=shared"))
gorm.Config
在上面的示例中,我们都用gorm.Open()打开数据库连接的,我们查看这个方法的源码,如:
func Open(dialector Dialector, opts ...Option) (db *DB, err error){
//省略
}
我们可以看到其实第一个参数外,后面还可以无限传入类型为Option的参数,用于配置连接参数,而Option是一个接口,如下:
// Option gorm option interface
type Option interface {
Apply(*Config) error
AfterInitialize(*DB) error
}
gorm.Config实现了Option接口,因此我们可以将gorm.Config传递给gorm.Open函数,gorm.Config的源码
// Config GORM config
type Config struct {
//跳过默认事务
SkipDefaultTransaction bool
// 命名策略,可以定义表名,列表等生成规则
NamingStrategy schema.Namer
// 在创建或更新时,是否更新关联数据
FullSaveAssociations bool
// 日志接口,用于实现自定义日志
Logger logger.Interface
// 创建时间使用的函数
NowFunc func() time.Time
// 生成 SQL 但不执行,可以用于准备或测试生成的 SQL
DryRun bool
// 是否禁止创建 prepared statement 并将其缓存
PrepareStmt bool
// 禁止去ping数据库,检测是否可用
DisableAutomaticPing bool
// 是否禁止自动创建外键约束
DisableForeignKeyConstraintWhenMigrating bool
// 是否禁止嵌套事务
DisableNestedTransaction bool
// 是否允许全局update/delete
AllowGlobalUpdate bool
// 执行查询时,是否带上所有字段
QueryFields bool
// 默认批量插入大小
CreateBatchSize int
}
下面是使用gorm.Config的参数来控制数据库连接的示例,如:
dsn := "user:pass@tcp(127.0.0.1:3306)/dbname?charset=utf8mb4&parseTime=True&loc=Local"
db, err := gorm.Open(mysql.Open(dsn), &gorm.Config{
SkipDefaultTransaction:true,
CreateBatchSize:1000,
})
连接池
database/sql
sqlDB, err := db.DB()
// SetMaxIdleConns 设置空闲连接池中连接的最大数量
sqlDB.SetMaxIdleConns(10)
// SetMaxOpenConns 设置打开数据库连接的最大数量。
sqlDB.SetMaxOpenConns(100)
// SetConnMaxLifetime 设置了连接可复用的最大时间。
sqlDB.SetConnMaxLifetime(time.Hour)
关闭数据库
sql.DB
sqlDB, err := db.DB()
sqlDB.Close()//defer sqlDB.Close()
小结
在这篇文章,我们学习了使用GORM去连接MySQL,PostgreSQL,SQLServer,SQLite等不同数据库的方式,可以看出连接不同的数据的方式大同小异,只是配置(Config)有些许不同,相信你应该已经掌握了吧!