package dbimport ("database/sql""fmt"_ "github.com/go-sql-driver/mysql""log""reflect""strconv""util"
)// 数据库操作处理结构体
type DB struct {pool  *sql.DBprefix stringtable  stringfield  stringwhere  stringgroup  stringhaving stringorder  stringlimit  stringargs   map[string][]interface{}
}func Open(c map[string]string)(dbPool DB,err error) {//var dbPool DB //等同 dbPool = new(DB)dsn:= fmt.Sprintf("%s:%s@tcp(%s:%s)/%s?charset=%s",c["db_user"],c["db_pwd"],c["db_host"],c["db_port"],c["db_name"], "utf8mb4,utf8")connPool,err:= sql.Open("mysql", dsn)//创建连接池,此时只是初始化了连接池,并没有连接数据库if err!= nil {return}connMaxOpen := util.Str_to_int(c["db_max_open"],10)connMaxIdle := util.Str_to_int(c["db_max_idle"],5)connPool.SetMaxOpenConns(connMaxOpen)//是设置的最大连接数,也就是甭管你多少并发,只能最多创建N条tcp连接,还有要注意的一点是,当执行完sql,连接转移到rows对象上,如果rows不关闭,这条连接不会被放回池里,其他并发获取不到连接会被阻塞住。connPool.SetMaxIdleConns(connMaxIdle)//是设置的执行完闲置的连接,这些就算是执行结束了连接还是会保留着的   简单点理解 上面那个是最大连接数  下面这个是最小连接数//connPool.SetConnMaxLifetime(time.Second * 15) //设置连接超时时间 一般不用设置 这样空置的连接会被一直保持 等待被复用err = connPool.Ping()if err != nil {return}dbPool.pool = connPooldbPool.prefix = c["db_prefix"]return
}//表名
func (this DB) Table(name string) DB {this.table = fmt.Sprintf("%s%s",this.prefix,name)return this
}//字段
func (this DB) Field(name string) DB {this.field = namereturn this
}//条件语句
func (this DB) Where(query string, params ...interface{}) DB {this.where = queryif(len(this.args)>0){//已有值this.args["where"] = params}else{this.args = map[string][]interface{}{"where":params}}return this
}//排序
func (this DB) Order(params string) DB {this.order = paramsreturn this
}//分组
func (this DB) Group(params string) DB {this.group = paramsreturn this
}//分组 HAVING
func (this DB) Having(query string, params ...interface{}) DB {this.having = queryif(len(this.args)>0){//已有值this.args["having"] = params}else{this.args = map[string][]interface{}{"having":params}}return this
}//限制
func (this DB) Limit(params string) DB {this.limit = paramsreturn this
}//-------------------------------------------------------------------------------------------------------------------------------------------------
// 获取第一条数据,返回数据类型为map
func (this DB) Get() map[string]interface{} {var RetOne map[string]interface{}this.limit = "1"GetSql := this.build_sql()GetArg := this.build_arg()rows, err := this.pool.Query(GetSql,GetArg...)if err != nil {log.Print("Get查询错误 ",GetSql,err)return RetOne}RetMap:= dealMysqlRows(rows)if len(RetMap) > 0 {RetOne = RetMap[0]}return RetOne
}
//获取单条数据的特定字段数据
func (this DB) GetVal(field string) interface{} {this.field = fieldRetMap:= this.Get()RetOne:= RetMap[field]return RetOne
}
//获取多条数据
func (this DB) GetList() []map[string]interface{} {GetSql := this.build_sql()GetArg := this.build_arg()rows, err := this.pool.Query(GetSql,GetArg...)if err != nil {log.Print("GetList查询错误 ",GetSql,err)return nil}RetMap := dealMysqlRows(rows)return RetMap
}
//判断是否有对应数据
func (this DB) Has() int{GetSql := "SELECT EXISTS(" + this.build_sql() + ")"GetArg := this.build_arg()rows,err:= this.pool.Query(GetSql,GetArg...)if err != nil {log.Print("Has查询错误 ",GetSql,err)return 0}RetMap := dealMysqlRows(rows)var RetOne intfor _,v:= range RetMap[0]{i,err:= strconv.Atoi(reflect.ValueOf(v).String())if(err!=nil){RetOne = 0}else{RetOne = i}}return RetOne
}
//新增
func (this DB) Insert(d map[string]interface{})(int,error){var Args []interface{}InsertTable,InsertCols,InsertArgs := this.table,"",""this.table = ""for k, v := range d {// 数据列只能为string类型if InsertCols == "" {InsertCols += fmt.Sprintf("%s", k)InsertArgs += "?"} else {InsertCols += fmt.Sprintf(",%s", k)InsertArgs += ",?"}Args = append(Args,v)}// 组合数据写入SQLSql := fmt.Sprintf("INSERT INTO %v (%v) VALUES (%v);", InsertTable, InsertCols, InsertArgs)retData, err1 := this.pool.Exec(Sql,Args...)if err1 != nil {log.Print("Insert错误 ",Sql,err1)return 0, nil}LastId, err2 := retData.LastInsertId()if err2 != nil {log.Print("Insert错误 ",Sql,err2)return 0, err2}return int(LastId), err2
}
//更新
func (this DB) Update(d map[string]interface{})(int,error){var Args []interface{}UpdateTable,UpdateArgs,UpdateWhere,UpdateOrder,UpdateLimit:= this.table,"","","",""this.table = ""for k, v := range d {// 数据列只能为string类型if UpdateArgs == "" {UpdateArgs += fmt.Sprintf("%s=?", k)} else {UpdateArgs += fmt.Sprintf(",%s=?", k)}Args = append(Args,v)}if len(this.where) > 0 {UpdateWhere = fmt.Sprintf(" WHERE %v", this.where)this.where = ""if(len(this.args)>0) {if (len(this.args["where"]) > 0) {Args = append(Args, this.args["where"]...)}this.args = nil}}else{//如果没有更新条件不更新 提示出错log.Print("Update错误 无更新条件")return 0, nil}if(len(this.order)>0) {UpdateOrder = fmt.Sprintf(" ORDER BY %v", this.order)this.order = ""}if(len(this.limit)>0) {UpdateLimit = fmt.Sprintf(" LIMIT %v", this.limit)this.limit = ""}Sql := fmt.Sprintf("UPDATE %v SET %v %v%v%v;",UpdateTable,UpdateArgs,UpdateWhere,UpdateOrder,UpdateLimit)retData, err1 := this.pool.Exec(Sql,Args...)if err1 != nil {log.Print("Update错误 ",Sql,err1)return 0, nil}ARows, err2 := retData.RowsAffected()if err2 != nil {log.Print("Update错误 ",Sql,err2)return 0, err2}return int(ARows), nil
}
//删除
func (this DB) Delete()(int,error){var Args []interface{}DeleteTable,DeleteWhere,DeleteOrder,DeleteLimit:= this.table,"","",""this.table = ""if len(this.where) > 0 {DeleteWhere = fmt.Sprintf(" WHERE %v", this.where)this.where = ""if(len(this.args)>0) {if (len(this.args["where"]) > 0) {Args = append(Args, this.args["where"]...)}this.args = nil}}else{//如果无条件不删除 提示出错log.Print("Delete错误 无删除条件")return 0, nil}if(len(this.order)>0) {DeleteOrder = fmt.Sprintf(" ORDER BY %v", this.order)this.order = ""}if(len(this.limit)>0) {DeleteLimit = fmt.Sprintf(" LIMIT %v", this.limit)this.limit = ""}// 组合删除数据SQLSql := fmt.Sprintf("DELETE FROM %v%v%v%v;",DeleteTable,DeleteWhere,DeleteOrder,DeleteLimit)fmt.Println(Sql)retData, err1 := this.pool.Exec(Sql,Args...)if err1 != nil {log.Print("Delete错误 ",Sql,err1)return 0, err1}ARows, err2 := retData.RowsAffected()if err2 != nil {log.Print("Delete错误 ",Sql,err2)return 0, err2}return int(ARows), nil
}
//原生
func (this DB) Query(Sql string,Args ...interface{}) []map[string]interface{} {rows, err := this.pool.Query(Sql,Args...)if err != nil {log.Print("Query查询错误 ",Sql,err)return nil}RetMap := dealMysqlRows(rows)return RetMap
}
//表名前缀
func (this DB) Pre(table_name string) string{return fmt.Sprintf("%s%s",this.prefix,table_name)
}
//获取当前SQL
func (this DB) GetSql() string{return this.build_sql()
}
//-------------------------------------------------------------------------------------------------------------------------------------------------//解析SQL 语句
func (this DB) build_sql() string {TableFilter,FieldFilter,WhereFilter,GroupFilter,HavingFilter,OrderFilter,LimitFilter:= this.table,"*","","","","",""if(len(TableFilter)>0) {this.table = ""}else{//如果表名为空 直接输出空return ""}if(len(this.field)>0) {FieldFilter = this.fieldthis.field = ""}if len(this.where) > 0 {WhereFilter = fmt.Sprintf(" WHERE %v", this.where)this.where = ""}if(len(this.group)>0) {GroupFilter = fmt.Sprintf(" GROUP BY %v", this.group)this.group = ""}if(len(this.having)>0) {HavingFilter = fmt.Sprintf(" HAVING %v", this.having)}if(len(this.order)>0) {OrderFilter = fmt.Sprintf(" ORDER BY %v", this.order)this.order = ""}if(len(this.limit)>0) {LimitFilter = fmt.Sprintf(" LIMIT %v", this.limit)this.limit = ""}Sql := fmt.Sprintf("SELECT %v FROM %v%v%v%v%v%v", FieldFilter, TableFilter, WhereFilter, GroupFilter, HavingFilter, OrderFilter, LimitFilter)return Sql
}
//解析SQL 语句占位符 值
func (this DB) build_arg() []interface{} {var Args []interface{}if(len(this.args)>0) {if(len(this.args["where"])>0){Args = append(Args,this.args["where"]...)}if (len(this.args["having"]) > 0) {Args = append(Args,this.args["having"]...)}this.args = nil}return Args
}// 数据库返回数据处理,返回数据类型为slice,slice内层为map
func dealMysqlRows(rows *sql.Rows) []map[string]interface{} {defer rows.Close()columns, _:= rows.Columns()// 获取列名columnTypes, _:= rows.ColumnTypes()// 获取每列的数据类型ColumnTypeMap := make(map[string]string)for _, v := range columnTypes {ColumnTypeMap[v.Name()] = v.DatabaseTypeName()}// 定义返回参数的sliceretValues := make([]sql.RawBytes, len(columns))// 定义数据列名的slicescanArgs := make([]interface{}, len(retValues))// 数据列赋值for i := range retValues {scanArgs[i] = &retValues[i]}// 定义返回数据类型slicevar resList []map[string]interface{}// 返回数据赋值for rows.Next() {// Scan将当前行各列结果填充进指定的各个值中_=rows.Scan(scanArgs...)// 内层数据格式rowMap := make(map[string]interface{})for i, colVal := range retValues {if colVal != nil {keyName := columns[i]value := string(colVal)// 数据类型转换switch ColumnTypeMap[keyName] {case "MEDIUMINT","INT","TINYINT":newValue, _ := strconv.Atoi(value)//字符串转introwMap[keyName] = newValuecase "VARCHAR":rowMap[keyName] = valuecase "DATETIME"://newValue, _ := time.ParseInLocation(value,value,time.Local)//rowMap[keyName] = newValuerowMap[keyName] = valuedefault:rowMap[keyName] = value}}}resList = append(resList, rowMap)}return resList
}

大佬写的orm框架,mark一下稍后阅读

大佬写的orm框架,mark一下稍后阅读相关推荐

  1. Java之手写实现ORM框架

    借鉴Mybatis框架手写一个ORM框架.mybatis整体架构中的整体思路是,首先解析一下配置文件,一个是框架的全局配置文件,一个是mapper配置文件,定义格式如下 <configurati ...

  2. 手写MyBatis ORM框架

    手写MyBatis ORM框架 目标: 实现: 思路: 一.前期准备 1.加入依赖 2.自定义插入注解 3.自定义删除注解 4.自定义更新注解 5.自定义查询注解 6.自定义参数注解 7.定义和数据库 ...

  3. 手写ORM框架----(数据库单表CRUD万能框架)

    目录 一.准备 1.1 ORM介绍 1.2 准备工作 二.手写ORM的CRUD 2.1 数据库准备 2.2 所需注解 2.3 实体类student 2.4 CRUD 2.4.1 添加功能 2.4.2 ...

  4. 自己动手写ORM框架

    自己动手写ORM框架(九):实现删除功能Remove方法 奋斗 2010-07-03 19:29 阅读:1962 评论:6   自己动手写ORM框架(八):实现修改功能Update方法 奋斗 2010 ...

  5. 手写数据库查询框架ORM

    我们不重复制造轮子,这里主要写的是如何封装JDBC,实现将数据库查询直接映射成javaBean,实现数据与对象的查询与映射.进阶可以思考开源框架hibernate,mybatis.JPA的底层是如何实 ...

  6. 自己动手写一个Golang ORM框架

    作者:smallyang,腾讯 IEG 运营开发工程师 当我深入的学习和了解了 GORM,XORM 后,我还是觉得它们不够简洁和优雅,有些笨重,有很大的学习成本.本着学习和探索的目的,于是我自己实现了 ...

  7. java orm框架 博客园_自己写ORM框架 DBUtils

    ORM框架想必大家都比较熟知了,即对象关系映射(英语:Object Relation Mapping,简称ORM,或O/RM,或O/R mapping),是一种程序技术,用于实现面向对象编程语言里不同 ...

  8. 核心技术靠化缘是要不来的——自己动手写ORM框架

    开源市场上的Java的ORM框架一个都不好用,所以花了几天时间自己撸了一个 OrmKids,欢迎大家下载学习.遇到问题请关注公众号进群大家一起讨论. OrmKids 支持分库分表的MySQL单表ORM ...

  9. nestjs 优秀的ORM框架sequelize操作数据库

    奉上最新代码: nestjs服务demo代码=>gitee地址.github地址 nodejs的ORM–sequelize 笔者在使用koa2开发后端服务的时候用的ORM框架是sequelize ...

最新文章

  1. xp系统安装oracle乱码,linux中安装Oracle汉字乱码完整解决方案
  2. ca 服务器的搭建 和证书的申请与颁发
  3. 字节跳动 1/3 员工不支持取消大小周,员工:每年少赚 10 万块
  4. 漏洞:阿里云盾phpMyAdmin =4.8.1 后台checkPageValidity函数缺陷可导致GETSHELL
  5. redux-form(V7.4.2)笔记(一)
  6. shujufenxi:一季度中国人每天存700亿元!“报复性存款”能带来消费吗?
  7. 【程序员比赛】CISCN 2021 ezj4va与Fix思路
  8. 语音情感识别----语音特征集之eGeMAPS,ComParE,09IS,BoAW
  9. 学习:ASP.NET中App_Code,App_Data等文件夹的作用(转)
  10. web页面锁屏初级尝试
  11. Kafka Connect在MapR上
  12. 我最喜欢的二十句名言
  13. Canvas基础-粒子动画Part2
  14. “21天好习惯“第一期-4
  15. 第11章 Docker 中 Gitlab 的安装与配置
  16. ValueError:only one element tensors can be converted to Python scalars解决办法
  17. 企业内部信息安全管理——(一)风险识别和管控
  18. 告别传智,重新上路----近5年来的总结及未来5年的计划
  19. i5 12400f和i5 12600kf参数对比
  20. 贪心算法(Greedy Algorithms)

热门文章

  1. unity android 符号表,如何获取libunity.so的符号表
  2. C# 错误 175: 具有固定名称“System.Data.SQLite.EF6”的 ADO.NET 提供程序未在计算机或应用程序配置文件中注册或无法加载
  3. CSS盒子的三种类型(border-box、content-box)
  4. Github——git本地仓库建立与远程连接(最详细清晰版本!附简化步骤与常见错误)
  5. AxonFramework,存储库
  6. CentOS 6.5上安装Zabbix 2.4.8
  7. 解决左下角没有显示桌面图标
  8. Ubuntu 13.04设置root用户登录图形界面
  9. MySQL数据库的远程连接配置
  10. jQuery formValidator表单验证插件4.1.1提供下载