代码拉取完成,页面将自动刷新
package gmysql
import (
"bytes"
"context"
sql2 "database/sql"
"fmt"
"reflect"
"strings"
"time"
"github.com/jinzhu/gorm"
_ "github.com/jinzhu/gorm/dialects/mysql"
)
// 单个Mysql连接
type DBConn struct {
gorm *gorm.DB
tx bool // 是否是事务
// 引用配置, 用于cat埋点
groupConf *DBGroupConf
subGroupConf *DBSubGroupConf
connConf *DBConnConf
}
func newDBConnection(groupConf *DBGroupConf, subGroupConf *DBSubGroupConf, connConf *DBConnConf) (dbConn *DBConn, err error) {
initOptions(groupConf, subGroupConf, connConf)
DSN := fmt.Sprintf("%s:%s@tcp(%s:%d)/%s?charset=utf8mb4&parseTime=True&loc=Local&readTimeout=%dms&writeTimeout=%dms&timeout=%dms",
groupConf.Username, groupConf.Password, connConf.Host, connConf.Port, groupConf.Database, subGroupConf.ReadTimeout, subGroupConf.WriteTimeout, subGroupConf.Timeout)
db, err := gorm.Open("mysql", DSN)
if err != nil {
return
}
db.DB().SetConnMaxLifetime(time.Duration(subGroupConf.IdleTime) * time.Millisecond)
db.DB().SetMaxOpenConns(subGroupConf.MaxConn)
db.DB().SetMaxIdleConns(subGroupConf.IdleConn)
dbConn = &DBConn{
gorm: db,
groupConf: groupConf,
subGroupConf: subGroupConf,
connConf: connConf,
}
return
}
// 初始化默认值
func initOptions(groupConf *DBGroupConf, subGroupConf *DBSubGroupConf, connConf *DBConnConf) {
if subGroupConf.MaxConn <= 0 {
subGroupConf.MaxConn = DEFAULT_MAX_CONN
}
if subGroupConf.IdleConn <= 0 {
subGroupConf.IdleConn = DEFAULT_IDLE_CONN
}
if subGroupConf.ReadTimeout <= 0 {
subGroupConf.ReadTimeout = DEFAULT_READ_TIMEOUT
}
if subGroupConf.WriteTimeout <= 0 {
subGroupConf.WriteTimeout = DEFAULT_WRITE_TIMEOUT
}
if subGroupConf.Timeout <= 0 {
subGroupConf.Timeout = DEFAULT_TIMEOUT
}
}
// SQL查询
func (dbConn *DBConn) Query(context context.Context, result interface{}, sql string, values ...interface{}) (err error) {
var (
type1, type2, type3 reflect.Type
)
if type1 = reflect.TypeOf(result); type1.Kind() != reflect.Ptr { // type1是*[]*Element
return ERR_QUERY_RESULT_INVALID
}
if type2 = type1.Elem(); type2.Kind() != reflect.Slice { // type2是[]*Element
return ERR_QUERY_RESULT_INVALID
}
if type3 = type2.Elem(); type3.Kind() != reflect.Ptr { // type3是*Element
return ERR_QUERY_RESULT_INVALID
}
// 发起SQL查询
var rows *sql2.Rows
if rows, err = dbConn.gorm.Raw(sql, values...).Rows(); err != nil {
return
}
defer rows.Close() // rows.Next()可能由于panic,没有执行rows.Close()
for rows.Next() {
elem := reflect.New(type3.Elem()) // 创建*Element
if err = dbConn.gorm.ScanRows(rows, elem.Interface()); err != nil { // 填充*Element
return
}
newSlice := reflect.Append(reflect.ValueOf(result).Elem(), elem) // 将*Element追加到*result
reflect.ValueOf(result).Elem().Set(newSlice) // 将新slice赋值给*result
}
return
}
// SQL写入
func (dbConn *DBConn) Exec(context context.Context, sql string, values ...interface{}) (result int64, err error) {
var sqlResult sql2.Result
sqlType := dbConn.sqlType(sql)
// 执行SQL
if sqlResult, err = dbConn.gorm.CommonDB().Exec(sql, values...); err != nil {
return
}
// 判断SQL类型取不同结果
if sqlType == "INSERT" {
result, err = sqlResult.LastInsertId()
} else {
result, err = sqlResult.RowsAffected()
}
return
}
// 开启事务
func (dbConn *DBConn) Begin(context context.Context) (txConn *DBConn, err error) {
if dbConn.tx {
return nil, ERR_RECURSION_TX
}
clone := *dbConn
clone.gorm = dbConn.gorm.BeginTx(context, nil)
clone.tx = true
txConn = &clone
err = clone.getError()
return
}
// 提交事务
func (dbConn *DBConn) Commit(context context.Context) (err error) {
if !dbConn.tx {
return ERR_INVALID_TX
}
dbConn.gorm.Commit()
err = dbConn.getError()
return
}
func (dbConn *DBConn) getError() (err error) {
if errNum := len(dbConn.gorm.GetErrors()); errNum > 0 {
err = dbConn.gorm.GetErrors()[errNum-1]
}
return
}
// 回滚事务
func (dbConn *DBConn) Rollback(context context.Context) (err error) {
if !dbConn.tx {
return ERR_INVALID_TX
}
dbConn.gorm.Rollback()
err = dbConn.getError()
return
}
// 判断SQL类型
func (dbConn *DBConn) sqlType(sql string) string {
sql = strings.TrimLeft(sql, " \t\r\n")
buf := bytes.Buffer{}
for i := 0; i < len(sql); i++ {
if sql[i] != ' ' && sql[i] != '\t' && sql[i] != '\r' && sql[i] != '\n' {
buf.WriteByte(sql[i])
} else {
break
}
}
return strings.ToUpper(buf.String())
}
// 生成JDBC风格的DSN
func (dbConn *DBConn) JDBC() (dsn string) {
dsn = fmt.Sprintf("jdbc:mysql://%s:%d/%s?useUnicode=true&characterEncoding=utf8mb4&autoReconnect=true",
dbConn.connConf.Host, dbConn.connConf.Port, dbConn.groupConf.Database)
return
}
此处可能存在不合适展示的内容,页面不予展示。您可通过相关编辑功能自查并修改。
如您确认内容无涉及 不当用语 / 纯广告导流 / 暴力 / 低俗色情 / 侵权 / 盗版 / 虚假 / 无价值内容或违法国家有关法律法规的内容,可点击提交进行申诉,我们将尽快为您处理。