赞
踩
ORM框架操作数据库都需要预先定义模型,模型可以理解成数据模型,作为操作数据库的媒介。
例如:
在golang中gorm模型定义是通过struct实现的,这样我们就可以通过gorm库实现struct类型和mysql表数据的映射。
gorm模型定义主要就是在struct类型定义的基础上增加字段标签说明实现,下面看个完整的例子。
假如有个商品表,表结构如下
- CREATE TABLE `food` (
- `id` int(10) unsigned NOT NULL AUTO_INCREMENT COMMENT '自增ID,商品Id',
- `name` varchar(30) NOT NULL COMMENT '商品名',
- `price` decimal(10,2) unsigned NOT NULL COMMENT '商品价格',
- `type_id` int(10) unsigned NOT NULL COMMENT '商品类型Id',
- `createtime` int(10) NOT NULL DEFAULT 0 COMMENT '创建时间',
- PRIMARY KEY (`id`)
- ) ENGINE=InnoDB DEFAULT CHARSET=utf8
默认gorm对struct字段名使用Snake Case命名风格转换成mysql表字段名(需要转换成小写字母)。
根据gorm的默认约定,上面例子只需要使用gorm:"column:createtime"
标签定义为CreateTime字段指定表字段名,其他使用默认值即可。
提示:Snake Case命名风格,就是各个单词之间用下划线(_)分隔,例如: CreateTime的Snake Case风格命名为create_time
通过上面的例子,大家看到可以通过类似gorm:"column:createtime"
这样的标签定义语法,定义struct字段的列名(表字段名)。
gorm标签语法:gorm:"标签定义"
标签定义部分,多个标签定义可以使用分号(;)分隔
例如定义列名:
gorm:"column:列名"
gorm常用标签如下:
标签 | 说明 | 例子 |
---|---|---|
column | 指定列名 | gorm:"column:createtime" |
PRIMARY_KEY | 指定主键 | gorm:"column:id; PRIMARY_KEY" |
- | 忽略字段 | gorm:"-" 可以忽略struct字段,被忽略的字段不参与gorm的读写操作 |
可以通过定义struct类型的TableName函数实现定义模型的表名
接上面的例子:
- //设置表名,可以通过给Food struct类型定义 TableName函数,返回一个字符串作为表名
- func (v Food) TableName() string {
- return "food"
- }
建议: 默认情况下都给模型定义表名,有时候定义模型只是单纯的用于接收手写sql查询的结果,这个时候是不需要定义表名;手动通过gorm函数Table()指定表名,也不需要给模型定义TableName函数。
gorm支持多种数据库,这里主要介绍mysql,连接mysql主要有两个步骤:
配置DSN (Data Source Name)
gorm库使用dsn作为连接数据库的参数,dsn翻译过来就叫数据源名称,用来描述数据库连接信息。一般都包含数据库连接地址,账号,密码之类的信息。
DSN格式:
[username[:password]@][protocol[(address)]]/dbname[?param1=value1&...¶mN=valueN]
mysql连接dsn例子:
- //mysql dsn格式
- //涉及参数:
- //username 数据库账号
- //password 数据库密码
- //host 数据库连接地址,可以是Ip或者域名
- //port 数据库端口
- //Dbname 数据库名
- username:password@tcp(host:port)/Dbname?charset=utf8&parseTime=True&loc=Local
-
- //填上参数后的例子
- //username = root
- //password = 123456
- //host = localhost
- //port = 3306
- //Dbname = tizi365
- //后面K/V键值对参数含义为:
- // charset=utf8 客户端字符集为utf8
- // parseTime=true 支持把数据库datetime和date类型转换为golang的time.Time类型
- // loc=Local 使用系统本地时区
- root:123456@tcp(localhost:3306)/tizi365?charset=utf8&parseTime=True&loc=Local
-
- //gorm 设置mysql连接超时参数
- //开发的时候经常需要设置数据库连接超时参数,gorm是通过dsn的timeout参数配置
- //例如,设置10秒后连接超时,timeout=10s
- //下面是完成的例子
- root:123456@tcp(localhost:3306)/tizi365?charset=utf8&parseTime=True&loc=Local&timeout=10s
-
- //设置读写超时时间
- // readTimeout - 读超时时间,0代表不限制
- // writeTimeout - 写超时时间,0代表不限制
- root:123456@tcp(localhost:3306)/tizi365?charset=utf8&parseTime=True&loc=Local&timeout=10s&readTimeout=30s&writeTimeout=60s
使用gorm.Open连接数据库
有了上面配置的dsn参数,就可以使用gorm连接数据库,下面是连接数据库的例子
- package main
-
- import (
- //导入MYSQL数据库驱动,这里使用的是GORM库封装的MYSQL驱动导入包,实际上大家看源码就知道,这里等价于导入github.com/go-sql-driver/mysql
- //这里导入包使用了 _ 前缀代表仅仅是导入这个包,但是我们在代码里面不会直接使用。
- _ "github.com/jinzhu/gorm/dialects/mysql"
- "github.com/jinzhu/gorm"
- )
-
- func main() {
- //配置MySQL连接参数
- username := "root" //账号
- password := "123456" //密码
- host := "127.0.0.1" //数据库地址,可以是Ip或者域名
- port := 3306 //数据库端口
- Dbname := "tizi365" //数据库名
- timeout := "10s" //连接超时,10秒
-
- //拼接下dsn参数, dsn格式可以参考上面的语法,这里使用Sprintf动态拼接dsn参数,因为一般数据库连接参数,我们都是保存在配置文件里面,需要从配置文件加载参数,然后拼接dsn。
- dsn := fmt.Sprintf("%s:%s@tcp(%s:%d)/%s?charset=utf8&parseTime=True&loc=Local&timeout=%s", username, password, host, port, Dbname, timeout)
- //连接MYSQL, 获得DB类型实例,用于后面的数据库读写操作。
- db, err := gorm.Open("mysql", dsn)
- if err != nil {
- panic("连接数据库失败, error=" + err.Error())
- }
- //延时关闭数据库连接
- defer db.Close()
- }
gorm调试模式
为了方便调试,了解gorm操作到底执行了怎么样的sql语句,开发的时候需要打开调试日志,这样gorm会打印出执行的每一条sql语句。
使用LogMode函数,设置打印gorm执行的sql语句。
例子:
db.LogMode(true)
- //定义一个工具包,用来管理gorm数据库连接池的初始化工作。
- package tools
-
- //定义全局的db对象,我们执行数据库操作主要通过他实现。
- var _db *gorm.DB
-
- //包初始化函数,golang特性,每个包初始化的时候会自动执行init函数,这里用来初始化gorm。
- func init() {
- ...忽略dsn配置,请参考上面例子...
-
- // 声明err变量,下面不能使用:=赋值运算符,否则_db变量会当成局部变量,导致外部无法访问_db变量
- var err error
- //连接MYSQL, 获得DB类型实例,用于后面的数据库读写操作。
- _db, err = gorm.Open("mysql", dsn)
- if err != nil {
- panic("连接数据库失败, error=" + err.Error())
- }
-
- //设置数据库连接池参数
- _db.DB().SetMaxOpenConns(100) //设置数据库连接池最大连接数
- _db.DB().SetMaxIdleConns(20) //连接池最大允许的空闲连接数,如果没有sql任务需要执行的连接数大于20,超过的连接会被连接池关闭。
- }
-
- //获取gorm db对象,其他包需要执行数据库查询的时候,只要通过tools.getDB()获取db对象即可。
- //不用担心协程并发使用同样的db对象会共用同一个连接,db对象在调用他的方法的时候会从数据库连接池中获取新的连接
- func GetDB() *gorm.DB {
- return _db
- }
使用例子:
- package main
- //导入tools包
- import tools
-
- func main() {
- //获取DB
- db := tools.GetDB()
-
- //执行数据库查询操作
- u := User{}
- //自动生成sql: SELECT * FROM `users` WHERE (username = 'tizi365') LIMIT 1
- db.Where("username = ?", "tizi365").First(&u)
- }
注意:使用连接池技术后,千万不要使用完db后调用db.Close关闭数据库连接,这样会导致整个数据库连接池关闭,导致连接池没有可用的连接。
参考:https://www.tizi365.com/archives/18.html
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。