绑定完请刷新页面
取消
刷新

分享好友

×
取消 复制
iris 数据库配置及连接方法封装
2022-06-09 11:30:34

iris 数据库配置及连接方法封装

上一节讲完项目结构 & 生成数据表映射之后,接下来就是项目连接数据库操作数据库的代码封装:

连接数据库配置

数据库配置的主要目的就是为了把 Golang 链接数据库链接

"[User]:[Pwd]@tcp([Host]:[Port])/[DbName]?charset=[DbCharset]"

中的各项参数,变成结构体可标准配置
。比如:

    type DbConf struct {
    Host string
    Port int
    User string
    Pwd string
    DbName string
    DbCharset string
    }

    工业项目一般都涉及多人开发,开发维护的时候为了统一管理。开发组内都会有自己的代码标准,所以这也是项目需要这配置那配置的配置化
    原因

    真正链接数据库的时候,使用fmt
    格式化输出函数,就可以轻易获得链接数据库链接

      const DriverName  = "mysql"


      var MasterDbConf DbConf = DbConf{
      Host : "127.0.0.1",
      Port : 3306,
      User : "root",
      Pwd : "",
      DbName : "superstar",
      DbCharset: "utf8",
      }


      conf := MasterDbConf
      driverSource := fmt.Sprintf(
      "%s:%s@tcp(%s:%d)/%s?charset=%s",
      c.User, c.Pwd, c.Host, c.Port, c.DbName, c.DbCharset
      )
      fmt.Println(driverSource)


      masterEngine, err := xorm.NewEngine(conf.DriverName, driverSource)
      if err != nil {
      log.Fatal("dbhelper.DbInstanceMaster err:", err)
      return nil
      }

      配置可以不只一份,比如主从配置,读写分离。数据同步交给数据库主从同步,读取数据xorm.NewEngine
      注意使用从库配置即可:

        var SlaveDbConf DbConf = DbConf{
        Host : "127.0.0.1",
        Port : 3306,
        User : "root",
        Pwd : "",
        DbName : "superstar",
        DbCharset: "utf8",
        }

        到了实操阶段,我们在项目根目录下的conf
        文件夹建db.go
        文件:

        conf/db.go

          package conf


          const DriverName = "mysql"


          type DbConf struct {
          Host string
          Port int
          User string
          Pwd string
          DbName string
          }


          var MasterDbConf DbConf = DbConf{
          Host : "127.0.0.1",
          Port : 3306,
          User : "root",
          Pwd : "",
          DbName : "superstar",
          }


          var SlaveDbConf DbConf = DbConf{
          Host : "127.0.0.1",
          Port : 3306,
          User : "root",
          Pwd : "",
          DbName : "superstar",
          }

          连接数据库方法封装

          封装好数据库配置之后,为了使链接数据库方法变得一致,有利于日后统一管理。于是把上面提及的数据库链接方式封装成函数,就能在需要连接数据库时建立新的数据库链接。方便调用:

            package datasource


            import (
            "fmt"
            _ "github.com/go-sql-driver/mysql"
            "log"
            "superstar/conf"
            "sync"
            "xorm.io/xorm"
            )


            func InstanceMaster() *xorm.Engine {
            c := conf.MasterDbConf
            driverSource := fmt.Sprintf("%s:%s@tcp(%s:%d)/%s?charset=utf8",
            c.User, c.Pwd, c.Host, c.Port, c.DbName)
            fmt.Println(driverSource)


            masterEngine, err := xorm.NewEngine(conf.DriverName, driverSource)
            if err != nil {
            log.Fatal("dbhelper.DbInstanceMaster err:", err)
            return nil
            }


            return masterEngine
            }

            但每次操作数据库是,都建立新的数据库链接。不仅浪费数据库连接池资源、还容易在并发高情况下造成无法链接数据库。

            于是我们需要一个数据库链接对象masterEngine
            ,在链接数据库前,检查对象是否为空,不为空就复用数据库链接;为空则重新建立数据库链接:

              func InstanceMaster() *xorm.Engine {
              if masterEngine != nil {
              return masterEngine
              }


              c := conf.MasterDbConf
              driverSource := fmt.Sprintf("%s:%s@tcp(%s:%d)/%s?charset=utf8",
              c.User, c.Pwd, c.Host, c.Port, c.DbName)
              fmt.Println(driverSource)


              masterEngine, err := xorm.NewEngine(conf.DriverName, driverSource)
              if err != nil {
              log.Fatal("dbhelper.DbInstanceMaster err:", err)
              return nil
              }


              return masterEngine
              }

              并发情况下数据库链接

              但这里还有一个问题:

                if masterEngine != nil {
                return masterEngine
                }

                如果一下子,进来 10 个请求。第 1 个请求的 masterEngine
                 没来得及生成,导致后面 9 个请求也需要重复实例化 masterEngine
                 这种情况也不合理。

                为了避免这种情况,我们在实例化 masterEngine
                 时加锁:

                  if masterEngine != nil {
                  return masterEngine
                  }


                  lock.Lock()
                  defer lock.Unlock() 后解锁

                  协程情况下数据库链接

                  协程时,上面 10 个请求一起进来,每个都到 lock.Lock()
                   加锁挂起。等第 1 个请求解锁后,后面 9 个请求也逐个实例化 masterEngine
                   这种情况也不合理。

                  为了避免这种情况,我在再加锁之后再次 判断 masterEngine
                   是否已存在:

                    if masterEngine != nil {
                    return masterEngine
                    }


                    lock.Lock()
                    defer lock.Unlock()


                    // 协程时,上面十个一起进来,每个都到 lock.Lock() 加锁挂起。这里避免 个加锁然后创建实例后,每个协程都创建实例
                    if masterEngine != nil {
                    return masterEngine
                    }

                    到了实操阶段,我们在项目根目录下的datasource
                    文件夹建dbhelper.go
                    文件:

                    datasource/dbhelper.go

                      package datasource


                      import (
                      "fmt"
                      _ "github.com/go-sql-driver/mysql"
                      "log"
                      "superstar/conf"
                      "sync"
                      "xorm.io/xorm"
                      )


                      // 数据库单例 dbhelper.go
                      var (
                      masterEngine *xorm.Engine
                      slaveEngine *xorm.Engine
                      lock sync.Mutex
                      )


                      func InstanceMaster() *xorm.Engine {
                      if masterEngine != nil {
                      return masterEngine
                      }


                      lock.Lock()
                      defer lock.Unlock()


                      if masterEngine != nil {
                      return masterEngine
                      }


                      c := conf.MasterDbConf
                      driverSource := fmt.Sprintf("%s:%s@tcp(%s:%d)/%s?charset=utf8",
                      c.User, c.Pwd, c.Host, c.Port, c.DbName)
                      fmt.Println(driverSource)


                      masterEngine, err := xorm.NewEngine(conf.DriverName, driverSource)
                      if err != nil {
                      log.Fatal("dbhelper.DbInstanceMaster err:", err)
                      return nil
                      }


                      // DEBUG 模式,打印全部sql, 帮助对比 orm 与 sql 执行对照关系
                      masterEngine.ShowSQL(false)
                      masterEngine.SetTZLocation(conf.SysTimeLocation)


                      return masterEngine
                      }


                      来源 https://www.modb.pro/db/71044

                      分享好友

                      分享这个小栈给你的朋友们,一起进步吧。

                      InterSystems IRIS
                      创建时间:2022-04-12 15:29:26
                      InterSystems IRIS
                      展开
                      订阅须知

                      • 所有用户可根据关注领域订阅专区或所有专区

                      • 付费订阅:虚拟交易,一经交易不退款;若特殊情况,可3日内客服咨询

                      • 专区发布评论属默认订阅所评论专区(除付费小栈外)

                      技术专家

                      查看更多
                      • itt0918
                        专家
                      戳我,来吐槽~