Gorm
连接数据库
与Springboot那套比起来,我觉得使用方面比较难受,目前我使用gorm连接数据库是把url写在程序里面:
dsn := "root:6125@tcp(127.0.0.1:3306)/mybatis?charset=utf8mb4&parseTime=True&loc=Local"
db, err := gorm.Open(mysql.Open(dsn), &gorm.Config{
//设置命名规则
NamingStrategy: schema.NamingStrategy{
SingularTable: true,
},
//关闭事务
SkipDefaultTransaction: true,
})
官方有提到:Mysql驱动程序提供了一些高级配置可以初始化过程中使用:
db, err := gorm.Open(mysql.New(mysql.Config{
//配置……
}), &gorm.Config{})
配置参数如下:
- DSN: "gorm:gorm@tcp(127.0.0.1:3306)/gorm?charset=utf8&parseTime=True&loc=Local", // 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 版本自动配置
基本用法CRUD
在看了官方文档过后
我把使用gorm来操作简单的CRUD的方式,或者说代码风格分为两类:
- Raw:首先就是我最为熟悉的手写sql了,用法基本跟Java的Mybatis差不多
- 链式调用:基本上都是使用
db来点点点,经典orm操作
链式调用那个需要注意的是,查询操作的时候,需要最后进行Scan()操作进行对象的赋值,由于没有面向对象那样直接由orm层返回对应的实体类(结构体),gorm的查询返回更像是返回的一行(row)数据,点进源码可以到看:
是利用了go底层的反射进行赋值的
Hook
就以创建对象为例吧:
BeforeSave BeforeCreate AfterCreate AfterSave
func (u *User) AfterCreate(tx *gorm.DB) (err error) {
return
}
func (u *User) BeforeCreate(tx *gorm.DB) (err error) {
return
}
开始的时候还有点纳闷,我就定义了一个方法就可以实现钩子的功能了?于是我点进了方法名,发现,底层实现已经做好了约定:
// AfterCreate after create hooks
func AfterCreate(db *gorm.DB) {
if db.Error == nil && db.Statement.Schema != nil && !db.Statement.SkipHooks && (db.Statement.Schema.AfterSave || db.Statement.Schema.AfterCreate) {
callMethod(db, func(value interface{}, tx *gorm.DB) (called bool) {
if db.Statement.Schema.AfterCreate {
if i, ok := value.(AfterCreateInterface); ok {
called = true
db.AddError(i.AfterCreate(tx))
}
}
if db.Statement.Schema.AfterSave {
if i, ok := value.(AfterSaveInterface); ok {
called = true
db.AddError(i.AfterSave(tx))
}
}
return called
})
}
}
估计是做了一个回调,以达到拦截器(中间件)的实现
事务
如果没有事务上的严格要求,可以选择关闭在事务里执行写入操作,这将获得大约 30%+ 性能提升
全局禁用
SkipDefaultTransaction: true
在代码里面自己手动使用事务:
db.Transaction(func(tx *gorm.DB) error {
//这里开始使用tx进行数据库操作
if err := tx.Create(&User{UserHead: "ys"}).Error; err != nil {
return err
}
return nil
})