连接数据库

使用GORM连接数据库还是比较简单的,概括起来就是以下三个步骤:

  1. 引入gorm.io/gorm和对应数据库的驱动库,如gorm.io/driver/sqlite
  2. 调用对应驱动库的Open()或New()函数返回一个实现了gorm.Dialector接口的实例。
  3. 调用gorm.Open()方法传入一个gorm.Dialector接口的实例以初始一个gorm.DB对象。

通过上述三个步骤,最终获取一个gorm.DB对象,我们便可以使用该对象的方法操作数据库,如Create,Delete等方法。

MySQL

简单连接

下面是连接mysql数据库最简单的方式,我们只需要定义好dsn便可以了 

package main

import (
	"gorm.io/driver/mysql"
	"gorm.io/gorm"
)

var DB *gorm.DB

func main() {
	//user、password、IP、port、dbname
	dsn := "user:password@tcp(ip:port)/dbname?charset=utf8mb4&parseTime=True&loc=Local"
	db, err := gorm.Open(mysql.Open(dsn), &gorm.Config{
		SkipDefaultTransaction:                   false, //设置为 false 表示不跳过默认事务
		NamingStrategy:                           nil,   //设置为 nil,表示使用 GORM 的默认命名策略
		FullSaveAssociations:                     false, //设置为 false 表示不完整保存关联的记录
		Logger:                                   nil,   //设置为 nil,表示不设置自定义的日志记录器
		NowFunc:                                  nil,   //设置为 nil,表示使用 GORM 的默认时间函数
		DryRun:                                   false, //设置为 false,表示不执行模拟运行
		PrepareStmt:                              false, //设置为 false,表示不预先准备语句
		DisableAutomaticPing:                     false, //设置为 false,表示不禁用自动心跳检测
		DisableForeignKeyConstraintWhenMigrating: false, //设置为 false,表示在迁移时不禁用外键约束
		IgnoreRelationshipsWhenMigrating:         false, //设置为 false,表示在迁移时不忽略关系
		DisableNestedTransaction:                 false, //设置为 false,表示不禁用嵌套事务
		AllowGlobalUpdate:                        false, //设置为 false,表示不允许全局更新
		QueryFields:                              false, //设置为 false,表示不使用字段查询
		CreateBatchSize:                          0,     //设置为 0,表示使用 GORM 的默认批量创建大小
		TranslateError:                           false, //设置为 false,表示不转换错误
		ClauseBuilders:                           nil,   //设置为 nil,表示不设置自定义的查询子句构建器
		ConnPool:                                 nil,   //设置为 nil,表示使用 GORM 的默认连接池
		Dialector:                                nil,   //设置为 nil,表示使用 GORM 的默认方言(dialect)
		Plugins:                                  nil,   //设置为 nil,表示不使用任何插件
	})
	if err != nil {
		panic("数据库连接错误")
	}
	DB = db
}
mysql.New

如果我们在连接数据库时,想进一步配置,则可以使用mysql.New()函数,该函数可以传递一个mysql.Config进行详细配置,如:

package main

import (
	"gorm.io/driver/mysql"
	"gorm.io/gorm"
)

var DB *gorm.DB

func main() {
	//user、password、IP、port、dbname
	dsn := "user:password@tcp(ip:port)/dbname?charset=utf8mb4&parseTime=True&loc=Local"

	//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 版本自动配置
	//}))

	db, err := gorm.Open(mysql.New(mysql.Config{
		DriverName:                    dsn,   //驱动程序的名称,通常不需要手动设置,GORM 默认使用 mysql
		ServerVersion:                 "",    //服务器版本,通常在连接成功后由 GORM 自动设置
		DSN:                           "",    //数据源名称,这是一个包含数据库连接信息的字符串,格式通常为 username:password@tcp(address:port)/dbname?param=value
		DSNConfig:                     nil,   //一个 mysql.DSNConfig 类型的配置,用于进一步配置 DSN 字符串
		Conn:                          nil,   //一个原始的连接对象,通常不需要手动设置
		SkipInitializeWithVersion:     false, //设置为 false 表示不跳过使用服务器版本进行初始化
		DefaultStringSize:             0,     //默认的字符串大小,设置为 0 表示使用 GORM 的默认值
		DefaultDatetimePrecision:      nil,   //默认的 datetime 精度,这里设置为 nil,表示使用 GORM 的默认值
		DisableWithReturning:          false, //设置为 false 表示不禁用 WITH RETURNING 支持
		DisableDatetimePrecision:      false, //设置为 false 表示不禁用 datetime 精度支持
		DontSupportRenameIndex:        false, //以 DontSupport 开头的字段:这些字段表示是否不支持某些特定的数据库功能,这里全部设置为 false,表示没有禁用任何功能
		DontSupportRenameColumn:       false, //
		DontSupportForShareClause:     false, //
		DontSupportNullAsDefaultValue: false, //
		DontSupportRenameColumnUnique: false, //
		DontSupportDropConstraint:     false, //
	}))

	if err != nil {
		panic("数据库连接错误")
	}
	DB = db
}
通过sql.DB初始化*gorm.DB

如果我们自己使用database/sql打开一个数据库连接,那么也可以利用这个已经存在的连接,来初始化一个gorm.DB对象, 如:

package main

import (
	"database/sql"

	"gorm.io/driver/mysql"
	"gorm.io/gorm"
)

var DB *gorm.DB

func main() {

	db, err := sql.Open("mysql", "root:123qwe@tcp(localhost:3306)/mysql_db?charset=utf8&parseTime=True&loc=Local")
	if err != nil {
		panic(err)
	}
	DB, err = gorm.Open(mysql.New(mysql.Config{
		Conn: db,
	}))

	//都可以增删改查
	//db.Query("")
	//DB.Find("")
}

 PostgreSQL

简单连接
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.Open(dsn))
	if err != nil {
		panic(err)
	}
	db.Exec("")
}
 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,
	}))
	if err != nil {
		panic(err)
	}
	db.Exec("")
}
 通过sql.DB初始化*gorm.DB
package main

import (
	"database/sql"

	"gorm.io/driver/postgres"
	"gorm.io/gorm"
)

var DB *gorm.DB

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,
	}))
	if err != nil {
		panic(err)
	}
	DB = db
}

SQL Server

简单连接
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.Open(dsn))
	if err != nil {
		panic(err)
	}
}
 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数据

package main

import (
	"gorm.io/driver/sqlite" //驱动库
	"gorm.io/gorm"
)

func main() {
	db, err := gorm.Open(sqlite.Open("gorm.db")) //参数名随便,后缀也可以随便只要合法就可以
	/*
		SQLite 数据库文件并不一定要以 .db 为后缀名。SQLite 是一个非常灵活的数据库系统,它不关心文件的扩展名是什么。
		可以使用任何合法的文件名,包括但不限于 .db、.sqlite、.db3(这是 SQLite 默认的文件扩展名之一)或者其他任何您喜欢的名称
	*/
}

另外,连接SQLite数据库时,也可以在内存中创建临时数据库,而需要一个实际的数据库,SQLite 允许您使用特殊的语法来创建一个基于内存的数据库,这个数据库不会持久化到磁盘上,而是存储在内存中,基于内存的数据库在程序结束时会自动销毁,所有数据都会丢失。如果您需要在程序之间保留数据,您应该使用存储在磁盘上的数据库文件。

使用 :memory: 伪路径创建基于内存的数据库:
db, err := gorm.Open(sqlite.Open(":memory:"), &gorm.Config{})

使用 :memory: 会创建一个新的基于内存的数据库,每次程序运行时都会重新创建。这个数据库在程序结束时自动销毁。

使用 file::memory: 伪路径创建基于内存的数据库:
db, err := gorm.Open(sqlite.Open("file::memory:"), &gorm.Config{})

 file::memory::memory: 相似,也是创建基于内存的数据库。但是,file::memory: 允许 SQLite 使用更多的文件接口功能。

使用 file::memory:?cache=shared 创建共享缓存的基于内存数据库:
db, err := gorm.Open(sqlite.Open("file::memory:?cache=shared"), &gorm.Config{})

使用 cache=shared 参数可以创建一个所有数据库连接都共享同一数据库状态缓存的基于内存数据库。这可以提高并发访问数据库的性能。

 gorm.Config

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
}

 连接池

通过数据库连接池,我们可以避免频繁创建和销数据库连接所带来的开销,GROM的数据连接池底层是通过database/sql来实现的,所以其设置方法与database/sql是一样的 

sqlDB, err := db.DB()

// SetMaxIdleConns 设置空闲连接池中连接的最大数量
sqlDB.SetMaxIdleConns(10)

// SetMaxOpenConns 设置打开数据库连接的最大数量。
sqlDB.SetMaxOpenConns(100)

// SetConnMaxLifetime 设置了连接可复用的最大时间。
sqlDB.SetConnMaxLifetime(time.Hour)

 关闭数据库

程序执行结束后,需要关闭数据连接,而GORM的底层仍然是通过database/sql去连接数据库的,因此要通过gorm.DB对象的DB()方法返回的sql.DB来关闭数据库连接

sqlDB, err := db.DB()

sqlDB.Close()//defer sqlDB.Close()