實現mysql外層包裝,簡化使用
package mysqldb
// 引入go插件
import (
"base_api_go/tbkt/config"
"database/sql"
"fmt"
_ "github.com/go-sql-driver/mysql"
"log"
"reflect"
"strconv"
"strings"
"time"
)
// 設置DB全部變量
var db *sql.DB
var ConnPool map[string]*sql.DB
// 初始化數據庫鏈接
func DB(name string) *DBPool{
DBProxy := new(DBPool)
Conn := ConnPool[name]
DBProxy.MysqlConn = Conn
return DBProxy
}
func init(){
dbMap := make(map[string]*sql.DB)
for name, addr := range config.DBConfig{
var err error
db, err = sql.Open("mysql", addr)
// 設置連接池最大鏈接數--不能大於數據庫設置的最大鏈接數
db.SetMaxOpenConns(100)
// 設置最大空閒鏈接數--小於設置的鏈接數
db.SetMaxIdleConns(5)
// 設置數據庫鏈接超時時間--不能大於數據庫設置的超時時間
db.SetConnMaxLifetime(time.Second * 5)
if err != nil {
log.Println("鏈接異常")
}
dbMap[name] = db
}
ConnPool = dbMap
}
// 數據庫操作處理結構體
type DBPool struct {
MysqlConn *sql.DB `數據庫鏈接池`
DBName string `數據庫名字`
TableName string `數據表名字`
SelectCondition []interface{} `選擇條件`
WhereCondition []map[string]interface{} `查詢條件`
GroupCondition []interface{} `分組條件`
OrderCondition []interface{} `排序條件`
}
// 查詢數據表獲取
func(p *DBPool)Table(name string) *DBPool{
p.TableName = name
return p
}
// 查詢select條件入參,入參類似python的args
func(p *DBPool)Select(params ...interface{}) *DBPool{
p.SelectCondition = params
return p
}
// 查詢where條件入參,入參類似於python的args
func(p *DBPool)Filter(query interface{}, values ...interface{}) *DBPool{
p.WhereCondition = append(p.WhereCondition, map[string]interface{}{"query": query, "args": values})
return p
}
// 定義數據庫分組函數,入參類似於python的args
func(p *DBPool)GroupBy(params ...interface{}) *DBPool{
p.GroupCondition = params
return p
}
// 定義數據庫排序函數,入參類似於python的args
func(p *DBPool)OrderBy(params ...interface{}) *DBPool{
p.OrderCondition = params
return p
}
// SQL拼接處理
func (p *DBPool)Sql() string{
// 匿名函數interface轉slice--需要時調用
fn := func (arr interface{}) []interface{} {
v := reflect.ValueOf(arr)
if v.Kind() != reflect.Slice {
panic("The Filter Params Valid")
}
vLen := v.Len()
ret := make([]interface{}, vLen)
for i := 0; i < vLen; i++ {
ret[i] = v.Index(i).Interface()
}
return ret
}
// 處理select條件
SelectFilter := ""
for _, vs := range p.SelectCondition{
if SelectFilter == "" {
SelectFilter += fmt.Sprintf("%s", vs)
}else {
SelectFilter += fmt.Sprintf(",%s", vs)
}
}
// 沒有設置獲取數據字段,默認查詢全部
if SelectFilter == "" {
SelectFilter = "*"
}
// 處理where條件
WhereFilter := ""
if len(p.WhereCondition[0]) > 0{
FilterList := strings.Split(p.WhereCondition[0]["query"].(string), "AND")
// 匿名函數處理where入參, interface轉slice
WhereList := fn(p.WhereCondition[0]["args"])
// 組合where條件
for index, value := range FilterList{
// 參數分割,並去除空格
NewValue := strings.TrimSpace(strings.Split(value, "?")[0])
WhereValue := WhereList[index]
// 入參類型斷言
switch reflect.ValueOf(WhereValue).Kind(){
case reflect.Int:
if WhereFilter == "" {
WhereFilter += fmt.Sprintf("WHERE %v%d", NewValue, WhereList[index])
}else{
WhereFilter += fmt.Sprintf(" AND %v%d", NewValue, WhereList[index])
}
case reflect.String:
if WhereFilter == "" {
WhereFilter += fmt.Sprintf("WHERE %v'%v'", NewValue, WhereList[index])
}else{
WhereFilter += fmt.Sprintf(" AND %v'%v'", NewValue, WhereList[index])
}
case reflect.Slice:
// 匿名函數處理where入參, interface轉slice
NewList := fn(WhereValue)
FilterWhere := ""
for v := range NewList{
switch reflect.ValueOf(v).Kind() {
case reflect.Int:
if FilterWhere == "" {
FilterWhere += fmt.Sprintf("%d", v)
} else {
FilterWhere += fmt.Sprintf(",%d", v)
}
case reflect.String:
if FilterWhere == "" {
FilterWhere += fmt.Sprintf("'%v'", v)
} else {
FilterWhere += fmt.Sprintf(",'%v'", v)
}
default:
panic("1001:The Params Valid")
}
}
if WhereFilter == "" {
WhereFilter += fmt.Sprintf("WHERE %v (%v)", NewValue, FilterWhere)
}else{
WhereFilter += fmt.Sprintf(" AND %v (%v)", NewValue, FilterWhere)
}
default:
panic("1002:The Params Valid")
}
}
}
// 處理分組條件
GroupFilter := ""
for _, vg := range p.GroupCondition{
if GroupFilter == "" {
GroupFilter += fmt.Sprintf("GROUP BY %s", vg)
}else {
GroupFilter += fmt.Sprintf(",%s", vg)
}
}
// 處理排序條件
OrderFilter := ""
for _, vo := range p.OrderCondition{
if OrderFilter == "" {
OrderFilter += fmt.Sprintf("ORDER BY %s", vo)
}else {
OrderFilter += fmt.Sprintf(",%s", vo)
}
}
// 格式化生成SQL
Sql := fmt.Sprintf("SELECT %v FROM %v %v ", SelectFilter, p.TableName, WhereFilter)
return Sql
}
// 數據庫返回數據處理,返回數據類型爲slice,slice內層爲map
func dealMysqlRows(rows *sql.Rows) []map[string]interface{}{
defer rows.Close()
// 獲取列名
columns, err := rows.Columns()
columnTypes, _ := rows.ColumnTypes()
// 獲取每列的數據類型
ColumnTypeMap := make(map[string]string)
for _, v := range columnTypes{
ColumnTypeMap[v.Name()] = v.DatabaseTypeName()
}
CheckError(err, 0)
// 定義返回參數的slice
retValues := make([]sql.RawBytes, len(columns))
// 定義數據列名的slice
scanArgs := make([]interface{}, len(retValues))
// 數據列賦值
for i := range retValues{
scanArgs[i] = &retValues[i]
}
// 定義返回數據類型slice
var resList []map[string]interface{}
// 返回數據賦值
for rows.Next() {
// 檢測數據列是否超出
err = rows.Scan(scanArgs...)
CheckError(err, 0)
// 內層數據格式
rowMap := make(map[string]interface{})
for i, colVal := range retValues{
if colVal != nil{
keyName := columns[i]
value := string(colVal)
// 數據類型轉換
switch ColumnTypeMap[keyName] {
case "INT":
newValue, _ := strconv.Atoi(value)
rowMap[keyName] = newValue
case "TINYINT":
newValue, _ := strconv.Atoi(value)
rowMap[keyName] = newValue
case "VARCHAR":
rowMap[keyName] = value
case "DATETIME":
newValue, _ := time.Parse(value, value)
rowMap[keyName] = newValue
default:
rowMap[keyName] = value
}
}
}
resList = append(resList, rowMap)
}
return resList
}
// 獲取第一條數據,返回數據類型爲map
func(p *DBPool) Get() map[string]interface{}{
RetOne := make(map[string]interface{})
// 數據庫操作結束,釋放鏈接
GetSql := p.Sql() + "LIMIT 1"
rows, err := p.MysqlConn.Query(GetSql)
CheckError(err, 0)
// 數據獲取
RetMap := dealMysqlRows(rows)
if len(RetMap) > 0{
RetOne = RetMap[0]
}
return RetOne
}
// 獲取多條數據,返回數據類型爲slice,slice內層爲map
func(p *DBPool) All() []map[string]interface{}{
// 數據庫操作結束,釋放鏈接
GetSql := p.Sql()
rows, err := p.MysqlConn.Query(GetSql)
CheckError(err, 0)
// 數據獲取
RetMap := dealMysqlRows(rows)
return RetMap
}
// 定義創建數據方法,返回最後的ID
func(p *DBPool) Create(params map[string]interface{}) int{
// 數據庫操作結束,釋放鏈接
// 自定待創建的函數和參數
InsertCols, InsertArgs := "", ""
for k, v := range params{
// 數據列只能爲string類型
if InsertCols == "" {
InsertCols += fmt.Sprintf("%s", k)
}else {
InsertCols += fmt.Sprintf(",%s", k)
}
// 判斷數據類型,類型斷言判斷
switch v.(type) {
case int:
if InsertArgs == "" {
InsertArgs += fmt.Sprintf("%d", v)
}else {
InsertArgs += fmt.Sprintf(",%d", v)
}
case string:
if InsertArgs == "" {
InsertArgs += fmt.Sprintf("'%s'", v)
}else{
InsertArgs += fmt.Sprintf(",'%s'", v)
}
case float64:
if InsertArgs == "" {
InsertArgs += fmt.Sprintf("%f", v)
}else {
InsertArgs += fmt.Sprintf(",%f", v)
}
}
}
// 開啓MySql事務
tx, err := p.MysqlConn.Begin()
CheckError(err, 1)
// 組合數據寫入SQL
InsertSql := fmt.Sprintf("INSERT INTO %v(%v) VALUES (%v);", p.TableName, InsertCols, InsertArgs)
retData, err := p.MysqlConn.Exec(InsertSql)
CheckError(err, 0)
LastId, err := retData.LastInsertId()
if err != nil{
log.Println("數據創建失敗,事務回滾")
tx.Rollback()
}
tx.Commit()
return int(LastId)
}
// 定義更新數據方法,返回影響的行數
func(p *DBPool) Update(params map[string]interface{}) int{
// 數據庫操作結束,釋放鏈接
// 處理where條件
WhereFilter := ""
for _, vw := range p.WhereCondition{
if WhereFilter == "" {
WhereFilter += fmt.Sprintf("%s", vw)
}else {
WhereFilter += fmt.Sprintf(" AND %s", vw)
}
}
// 定義待創建的函數和參數
UpdateArgs := ""
for k, v := range params{
// 數據列只能爲string類型
if UpdateArgs == "" {
// 判斷數據類型,類型斷言判斷
switch v.(type) {
case int:
UpdateArgs += fmt.Sprintf("%s=%d", k, v)
case string:
UpdateArgs += fmt.Sprintf("%s='%s'", k, v)
case float64:
UpdateArgs += fmt.Sprintf("%s=%f", k, v)
}
}else {
// 判斷數據類型,類型斷言判斷
switch v.(type) {
case int:
UpdateArgs += fmt.Sprintf(",%s=%d", k, v)
case string:
UpdateArgs += fmt.Sprintf(",%s='%s'", k, v)
case float64:
UpdateArgs += fmt.Sprintf(",%s=%f", k, v)
}
}
}
// 組合數據更新SQL
UpdateSql := fmt.Sprintf("UPDATE %v SET %v WHERE %v;", p.TableName, UpdateArgs, WhereFilter)
// 開啓MySql事務
tx, err := p.MysqlConn.Begin()
CheckError(err, 1)
retData, err := p.MysqlConn.Exec(UpdateSql)
CheckError(err, 1)
ARows, err := retData.RowsAffected()
if err != nil{
log.Println("數據更新失敗,事務回滾")
tx.Rollback()
}
// 提交事務
tx.Commit()
return int(ARows)
}
// 定義刪除數據方法
func(p *DBPool) Delete() int{
// 數據庫操作結束,釋放鏈接
// 處理where條件
WhereFilter := ""
for _, vw := range p.WhereCondition{
if WhereFilter == "" {
WhereFilter += fmt.Sprintf("%s", vw)
}else {
WhereFilter += fmt.Sprintf(" AND %s", vw)
}
}
// 組合刪除數據SQL
DeleteSql := fmt.Sprintf("DELETE FROM %v WHERE %v", p.TableName, WhereFilter)
// 開啓MySql事務
tx, err := p.MysqlConn.Begin()
retData, err := p.MysqlConn.Exec(DeleteSql)
CheckError(err, 0)
ARows, err := retData.RowsAffected()
if err != nil{
log.Println("數據刪除失敗,事務回滾")
tx.Rollback()
}
// 提交事務
tx.Commit()
return int(ARows)
}
// 查詢執行SQL方法
func(p *DBPool) Execute(Sql string) int{
// 數據庫操作結束,釋放鏈接
retData, err := p.MysqlConn.Exec(Sql)
// 開啓MySql事務
tx, err := p.MysqlConn.Begin()
CheckError(err, 0)
ARows, err := retData.RowsAffected()
if err != nil{
log.Println("數據庫執行失敗,事務回滾")
tx.Rollback()
}
// 提交事務
tx.Commit()
return int(ARows)
}
// 定義執行SQL返回一條數據方法
func(p *DBPool) FetchOne(Sql string) map[string]interface{}{
// 數據庫操作結束,釋放鏈接
rows, err := p.MysqlConn.Query(Sql)
CheckError(err, 0)
// 數據獲取
RetMap := dealMysqlRows(rows)
return RetMap[0]
}
// 定義執行SQL返回多條數據方法
func(p *DBPool) FetchAll(Sql string) []map[string]interface{}{
// 數據庫操作結束,釋放鏈接
rows, err := p.MysqlConn.Query(Sql)
CheckError(err, 0)
// 數據獲取
RetMap := dealMysqlRows(rows)
return RetMap
}
使用
import . "mysqldb"
AccountData := DB("base").Table("auth_account").Filter("id=?", AccountId).Get()
// AccountData map類型