iot_server/internal/tools/sqldb/mysql/gorm.go

237 lines
5.4 KiB
Go

package mysql
import (
"errors"
"fmt"
"github.com/winc-link/hummingbird/internal/dtos"
"github.com/winc-link/hummingbird/internal/pkg/logger"
"gorm.io/gorm/clause"
"gorm.io/driver/mysql"
"gorm.io/gorm"
)
const (
// 顺序排序
AscOrder = "asc"
// 倒序排序
DescOrder = "desc"
// 默认排序字段
DefaultOrderField = "modified"
OrderFieldCreated = "created"
// 批量创建的每条sql最大条数
CreateBatchSize = 500
// 批量更新的每条sql最大条数
UpdateBatchSize = 10000
)
type runMode string
const (
//local runMode = "local"
remote = "remote"
)
type GormClient struct {
Pool *gorm.DB
}
type GormWriter struct {
lc logger.LoggingClient
}
func (gl *GormWriter) Printf(s string, values ...interface{}) {
gl.lc.Debugf(s, values...)
}
func (c *GormClient) Close() {
if c.Pool != nil {
db, err := c.Pool.DB()
if err == nil {
db.Close()
}
}
}
func NewGormClient(config dtos.Configuration, lc logger.LoggingClient) (*GormClient, error) {
dsn := config.Dsn
pool, err := gorm.Open(mysql.Open(dsn), &gorm.Config{})
if err != nil {
return nil, err
}
return &GormClient{Pool: pool}, nil
}
func (c *GormClient) InitTable(dos ...DataObject) error {
var tables = make([]interface{}, 0)
for _, do := range dos {
tables = append(tables, do)
}
return c.Pool.AutoMigrate(tables...)
}
func (c *GormClient) CloseSession() {
return
}
// CreateObject 添加
func (c *GormClient) CreateObject(object DataObject) (err error) {
return c.Pool.Table(object.TableName()).Create(object).Error
}
//DeleteObject 删除
func (c *GormClient) DeleteObject(object DataObject) (err error) {
return c.Pool.Table(object.TableName()).Delete(object).Error
}
//GetObject 获取结果
func (c *GormClient) GetObject(obCond DataObject, object DataObject) (err error) {
return c.Pool.Table(object.TableName()).Where(obCond).First(object).Error
}
// GetPreloadObject 预加载
func (c *GormClient) GetPreloadObject(obCond DataObject, object DataObject) (err error) {
return c.Pool.Table(object.TableName()).Preload("Properties").Preload("Events").Preload("Actions").Where(obCond).First(object).Error
}
// UpdateObject 更新数据
func (c *GormClient) UpdateObject(object DataObject) (err error) {
return c.Pool.Table(object.TableName()).Select("*").Updates(object).Error
}
//AssociationsUpdateObject 关联更新
func (c *GormClient) AssociationsUpdateObject(object DataObject) (err error) {
return c.Pool.Session(&gorm.Session{FullSaveAssociations: true}).Table(object.TableName()).Select("*").Updates(object).Error
}
//AssociationsDeleteObject 关联删除
func (c *GormClient) AssociationsDeleteObject(object DataObject) (err error) {
return c.Pool.Session(&gorm.Session{FullSaveAssociations: true}).Table(object.TableName()).Select(clause.Associations).Delete(object).Error
}
// 判断是否存在
func (c *GormClient) ExistObject(do DataObject) (exist bool, err error) {
var count int64
template := c.Pool.Table(do.TableName())
err = template.Where(do).Count(&count).Error
if err != nil {
if errors.Is(err, gorm.ErrRecordNotFound) {
return false, nil
}
return false, err
}
if count == 0 {
return false, nil
}
return true, nil
}
// 模糊查询参数
type LikeQueryParam struct {
Field string
Value string
Prefix bool
Suffix bool
}
// 排序查询参数
type OrderQueryParam struct {
Key string
Desc bool
}
// 默认按照最后修改时间进行逆序排序
func NewDefaultOrderQueryParam() *OrderQueryParam {
return &OrderQueryParam{
Key: DefaultOrderField,
Desc: true,
}
}
// 条件查询
func (c *GormClient) GetObjects(doCond DataObject, do DataObject, likeParam *LikeQueryParam, order *OrderQueryParam, offset, limit int) (list []interface{}, count int64, err error) {
template := c.Pool.Table(do.TableName())
if doCond != nil {
template = template.Where(doCond)
}
if likeParam != nil {
var value = likeParam.Value
if likeParam.Prefix {
value = "%" + value
}
if likeParam.Suffix {
value = value + "%"
}
template = template.Where(fmt.Sprintf("%v LIKE ?", likeParam.Field), value)
}
if err = template.Count(&count).Error; err != nil {
return
}
if order != nil {
orderKey := order.Key
if order.Desc {
orderKey = fmt.Sprintf("%v %v", orderKey, DescOrder)
} else {
orderKey = fmt.Sprintf("%v %v", orderKey, AscOrder)
}
template = template.Order(orderKey)
}
rows, err := template.Limit(limit).Offset(offset).Rows()
if err != nil {
return
}
defer rows.Close()
list = make([]interface{}, 0, count)
for rows.Next() {
if err = c.Pool.ScanRows(rows, do); err != nil {
return
}
list = append(list, do.Get())
}
return
}
/*
fields: 全字段名称列表
conflictFields: 唯一字段名称列表
updateFields: 更新字段名称列表
record: 更新数据列表
*/
func (c *GormClient) BatchUpdate(fields, conflictFields, updateFields []string, tableName string, records [][]interface{}) error {
if len(records) == 0 {
return nil
}
var provider = &batchProvider{
TableName: tableName,
Fields: fields,
ConflictFields: conflictFields,
UpdateFields: updateFields,
BatchAmount: UpdateBatchSize,
}
return provider.Update(c.Pool, records)
}
func (c *GormClient) ExecSqlWithTransaction(funcs ...func(db *gorm.DB) error) error {
tx := c.Pool.Begin()
defer func() {
if r := recover(); r != nil {
tx.Rollback()
}
}()
for _, f := range funcs {
err := f(tx)
if err != nil {
tx.Rollback()
return err
}
}
return tx.Commit().Error
}