Watch 1 Star 6 Fork 0

goflyfox / gfstudy

Create your Gitee Account
Explore and code with more than 5 million developers,Free private repositories !:)
Sign up
This repository doesn't specify license. Without author's permission, this code is only for learning and cannot be used for other purposes.
golang基础教程-go语言快速入门 spread retract

https://www.bilibili.com/video/bv157411Z7Le

Clone or download
08.goframe数据库操作.md 8.46 KB
Copy Edit Web IDE Raw Blame History
zcool321@sina.com authored 2020-03-24 01:02 . update database example

Goframe数据库操作

一、基本介绍

gf框架的ORM功能由gdb模块实现,用于常用关系型数据库的ORM操作。其最大的特色在于同时支持mapstruct两种方式操作数据库。gdb默认情况下使用的是map数据类型作为基础的数据表记录载体,开发者无需预先定义数据表记录struct便可直接对数据表记录执行各种操作。这样的设计赋予了开发者更高的灵活度和简便性。

支持的数据库类型:Mysql,SQLite,PostgreSQL,SQLServer,Oracle

二、配置文件

推荐使用配置文件及单例对象来管理和使用数据库操作。

如果我们使用g对象管理模块中的g.DB("数据库分组名称")方法获取数据库操作对象,数据库对象将会自动读取config.toml配置文件中的相应配置项(通过配置管理模块),并自动初始化该数据库操作的单例对象。

[database]
    [[database.default]]
        link = "mysql:root:12345678@tcp(127.0.0.1:3306)/test"
    [[database.user]]
        link = "mysql:root:12345678@tcp(127.0.0.1:3306)/user"

注意每一项分组配置均可以是多个节点,支持负载均衡权重策略。如果不使用多节点负载均衡特性,仅使用配置分组特性,也可以简化为如下格式:

[database]
    [database.default]
        link = "mysql:root:12345678@tcp(127.0.0.1:3306)/test"
    [database.user]
        link = "mysql:root:12345678@tcp(127.0.0.1:3306)/user"

如果仅仅是单数据库节点,不使用配置分组特性,那么也可以简化为如下格式:

[database]
    link = "mysql:root:12345678@tcp(127.0.0.1:3306)/test"

不同数据类型对应的linkinfo如下:

数据库类型 Linkinfo配置 更多参数
mysql mysql: 账号:密码@tcp(地址:端口)/数据库名称 mysql
pgsql pgsql: user=账号 password=密码 host=地址 port=端口 dbname=数据库名称 pq
mssql mssql: user id=账号;password=密码;server=地址;port=端口;database=数据库名称;encrypt=disable go-mssqldb
sqlite sqlite: 文件绝对路径 (如: /var/lib/db.sqlite3) go-sqlite3
oracle oracle: 账号/密码@地址:端口/数据库名称 go-oci8

三、日志输出配置

gdb支持日志输出,内部使用的是glog.Logger对象实现日志管理,并且可以通过配置文件对日志对象进行配置。默认情况下gdb关闭了DEBUG日志输出,如果需要打开DEBUG信息需要将数据库的debug参数设置为true。以下是为一个配置文件示例:

[database]
    [database.logger]
        Path   = "/var/log/gf-app/sql"
        Level  = "all"
        Stdout = true
    [database.primary]
        link   = "mysql:root:12345678@tcp(127.0.0.1:3306)/user_center"
        debug  = true

其中database.logger即为gdb的日志配置,当该配置不存在时,将会使用日志组件的默认配置

四、数据结构

为便于数据表记录的操作,ORM定义了5种基本的数据类型:

type Map         map[string]interface{} // 数据记录
type List        []Map                  // 数据记录列表

type Value       *gvar.Var              // 返回数据表记录值
type Record      map[string]Value       // 返回数据表记录键值对
type Result      []Record               // 返回数据表记录列表
  1. MapList用于ORM操作过程中的输入参数类型(与全局类型g.Mapg.List一致,在项目开发中常用g.Mapg.List替换);
  2. Value/Record/Result用于ORM操作的结果数据类型;

五、数据库操作

Insert/Replace/Save

这三个链式操作方法用于数据的写入,并且支持自动的单条或者批量的数据写入,三者区别如下:

  1. Insert

    使用INSERT INTO语句进行数据库写入,如果写入的数据中存在主键或者唯一索引时,返回失败,否则写入一条新数据;

  2. Replace

    使用REPLACE INTO语句进行数据库写入,如果写入的数据中存在主键或者唯一索引时,会删除原有的记录,必定会写入一条新记录;

  3. Save

    使用INSERT INTO语句进行数据库写入,如果写入的数据中存在主键或者唯一索引时,更新原有数据,否则写入一条新数据;

在部分数据库类型中,并不支持Replace/Save方法

Update更新方法

Update用于数据的更新,往往需要结合DataWhere方法共同使用。Data方法用于指定需要更新的数据,Where方法用于指定更新的条件范围。同时,Update方法也支持直接给定数据和条件参数。

Delete删除方法

Delete方法用于数据的删除。

Where/And/Or查询条件

这三个方法用于传递查询条件参数,支持的参数为任意的string/map/slice/struct/*struct类型。

Where条件参数推荐使用字符串的参数传递方式(并使用?占位符预处理),因为map/struct类型作为查询参数无法保证顺序性,且在部分情况下(数据库有时会帮助你自动进行查询索引优化),数据库的索引和你传递的查询条件顺序有一定关系。

当使用多个Where方法连接查询条件时,作用同And。 此外,当存在多个查询条件时,gdb会默认将多个条件分别使用()符号进行包含,这种设计可以非常友好地支持查询条件分组。

All/One/Value/Count数据查询

这四个方法是数据查询比较常用的方法:

  1. All 用于查询并返回多条记录的列表/数组。
  2. One 用于查询并返回单条记录。
  3. Value 用于查询并返回一个字段值,往往需要结合Fields方法使用。
  4. Count 用于查询并返回记录数。

此外,也可以看得到这四个方法定义中也支持条件参数的直接输入,参数类型与Where方法一致。但需要注意,其中Value方法的参数中至少应该输入字段参数。

数据库表

CREATE TABLE `user` (
  `uid` int(11) NOT NULL AUTO_INCREMENT,
  `name` varchar(255) DEFAULT NULL,
  `site` varchar(255) DEFAULT NULL,
  PRIMARY KEY (`uid`)
) ENGINE=InnoDB AUTO_INCREMENT=10000 ;

示例

package test

import (
	"fmt"
	"github.com/gogf/gf/frame/g"
	"testing"
)

// Insert
func TestInsert(t *testing.T) {
	// INSERT INTO `user`(`name`) VALUES('john')
	_, err := g.DB().Table("user").Data(g.Map{"uid": 10000, "name": "john"}).Insert()
	if err != nil {
		panic(err)
	}
}

// Update
func TestUpdate(t *testing.T) {
	// UPDATE `user` SET `name`='john guo' WHERE name='john'
	_, err := g.DB().Table("user").Data("name", "john guo").
		Where("name", "john").Update()
	if err != nil {
		panic(err)
	}
}

// Delete
func TestDelete(t *testing.T) {
	// DELETE FROM `user` WHERE uid=10
	_, err := g.DB().Table("user").Where("uid", 10000).Delete()
	if err != nil {
		panic(err)
	}
}

// Select Where
func TestWhere(t *testing.T) {
	// INSERT INTO `user`(`name`) VALUES('john')
	g.DB().Table("user").Data(g.Map{"uid": 10001, "name": "john"}).Insert()
	g.DB().Table("user").Data(g.Map{"uid": 10002, "name": "john2"}).Insert()
	// 数量
	count, err := g.DB().Table("user").Where("uid", 10001).Count()
	if err != nil {
		panic(err)
	}
	fmt.Println("count:", count)
	// 获取单个值
	v, err := g.DB().Table("user").Where("uid", 10001).Fields("name").Value()
	if err != nil {
		panic(err)
	}
	fmt.Println("name:", v.String())
	// 查询对象
	r, err := g.DB().Table("user").Where("uid", 10002).One()
	if err != nil {
		panic(err)
	}
	fmt.Println("name:", r.Map()["name"])
	// 查询对象
	//l, err := g.DB().Table("user").As("t").Where("t.uid > ?", 10000).All()
	// 也可以简写为 select * from user as t where t.uid > 10000
	l, err := g.DB().Table("user").As("t").All("t.uid > ?", 10000)
	if err != nil {
		panic(err)
	}
	for index, value := range l {
		fmt.Println(index, value["uid"], value["name"])
	}
	g.DB().Table("user").Where("uid", 10001).Delete()
	g.DB().Table("user").Where("uid", 10002).Delete()
}

Comment ( 0 )

Sign in for post a comment

1
https://gitee.com/goflyfox/gfstudy.git
git@gitee.com:goflyfox/gfstudy.git
goflyfox
gfstudy
gfstudy
master

Search