本文整理自网络,侵删。
目录
- sqlx实战
- 准备工作
- 编写代码
- 添加引用
- 创建连接
- 增删改查
- 预处理语句
- 数据库事务
- sqlx干了什么
- MustXXX
- NamedXXX
- XXXScan
sqlx是Golang中的一个知名三方库,其为Go标准库database/sql提供了一组扩展支持。使用它可以方便的在数据行与Golang的结构体、映射和切片之间进行转换,从这个角度可以说它是一个ORM框架;它还封装了一系列地常用SQL操作方法,让我们用起来更爽。
sqlx实战
这里以操作MySQL的增删改查为例。
准备工作
先要准备一个MySQL,这里通过docker快速启动一个MySQL 5.7。
docker run -d --name mysql1 -p 3306:3306 -e MYSQL_ROOT_PASSWORD=123456 mysql:5.7
在MySQL中创建一个名为test的数据库:
CREATE DATABASE `test` /*!40100 DEFAULT CHARACTER SET utf8mb4 */;
数据库中创建一个名为Person的数据库表:
CREATE TABLE test.Person ( Id integer auto_increment NOT NULL, Name VARCHAR(30) NULL, City VARCHAR(50) NULL, AddTime DATETIME NOT NULL, UpdateTime DATETIME NOT NULL, CONSTRAINT Person_PK PRIMARY KEY (Id) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci;
然后创建一个Go项目,安装sqlx:
go get github.com/jmoiron/sqlx
因为操作的是MySQL,还需要安装MySQL的驱动:
go get github.com/go-sql-driver/mysql
编写代码
添加引用
添加sqlx和mysql驱动的引用:
import ( "log" _ "github.com/go-sql-driver/mysql" "github.com/jmoiron/sqlx" )
MySQL的驱动是隐式注册的,并不会在接下来的程序中直接调用,所以这里加了下划线。
创建连接
操作数据库前需要先创建一个连接:
db, err := sqlx.Connect("mysql", "root:123456@tcp(127.0.0.1:3306)/test?charset=utf8mb4&parseTime=true&loc=Local") if err != nil { log.Println("数据库连接失败") }
这个连接中指定了程序要用MySQL驱动,以及MySQL的连接地址、用户名和密码、数据库名称、字符编码方式;这里还有两个参数parseTime和loc,parseTime的作用是让MySQL中时间类型的值可以映射到Golang中的time.Time类型,loc的作用是设置time.Time的值的时区为当前系统时区,不使用这个参数的话保存到的数据库的就是UTC时间,会和北京时间差8个小时。
增删改查
sqlx扩展了DB和Tx,继承了它们原有的方法,并扩展了一些方法,这里主要看下这些扩展的方法。
增加
通用占位符的方式:
insertResult := db.MustExec("INSERT INTO Person (Name, City, AddTime, UpdateTime) VALUES (?, ?, ?, ?)", "Zhang San", "Beijing", time.Now(), time.Now()) lastInsertId, _ := insertResult.LastInsertId() log.Println("Insert Id is ", lastInsertId)
这个表的主键使用了自增的方式,可以通过返回值的LastInsertId方法获取。
命名参数的方式:
insertPerson := &Person{ Name: "Li Si", City: "Shanghai", AddTime: time.Now(), UpdateTime: time.Now(), } insertPersonResult, err := db.NamedExec("INSERT INTO Person (Name, City, AddTime, UpdateTime) VALUES(:Name, :City, :AddTime, :UpdateTime)", insertPerson)
命名参数的方式是sqlx扩展的,这个方式就是常说的ORM。这里需要注意给struct字段添加上db标签:
type Person struct { Id int `db:"Id"` Name string `db:"Name"` City string `db:"City"` AddTime time.Time `db:"AddTime"` UpdateTime time.Time `db:"UpdateTime"` }
struct中的字段名称不必和数据库字段相同,只需要通过db标签映射正确就行。注意SQL语句中使用的命名参数需要是db标签中的名字。
除了可以映射struct,sqlx还支持map,请看下面这个示例:
insertMap := map[string]interface{}{ "n": "Wang Wu", "c": "HongKong", "a": time.Now(), "u": time.Now(), } insertMapResult, err := db.NamedExec("INSERT INTO Person (Name, City, AddTime, UpdateTime) VALUES(:n, :c, :a, :u)", insertMap)
再来看看批增加的方式:
insertPersonArray := []Person{ {Name: "BOSIMA", City: "Wu Han", AddTime: time.Now(), UpdateTime: time.Now()}, {Name: "BOSSMA", City: "Xi An", AddTime: time.Now(), UpdateTime: time.Now()}, {Name: "BOMA", City: "Cheng Du", AddTime: time.Now(), UpdateTime: time.Now()}, } insertPersonArrayResult, err := db.NamedExec("INSERT INTO Person (Name, City, AddTime, UpdateTime) VALUES(:Name, :City, :AddTime, :UpdateTime)", insertPersonArray) if err != nil { log.Println(err) return } insertPersonArrayId, _ := insertPersonArrayResult.LastInsertId() log.Println("InsertPersonArray Id is ", insertPersonArrayId)
这里还是采用命名参数的方式,参数传递一个struct数组或者切片就可以了。这个执行结果中也可以获取到最后插入数据的自增Id,不过实测返回的是本次插入的第一条的Id,这个有点别扭,但是考虑到增加多条只获取一个Id的场景似乎没有,所以也不用多虑。
除了使用struct数组或切片,也可以使用map数组或切片,这里就不贴出来了,有兴趣的可以去看文末给出的Demo链接。
删除
删除也可以使用通用占位符和命名参数的方式,并且会返回本次执行受影响的行数,某些情况下可以使用这个数字判断SQL实际有没有执行成功。
deleteResult := db.MustExec("Delete from Person where Id=?", 1) log.Println(deleteResult.RowsAffected()) deleteMapResult, err := db.NamedExec("Delete from Person where Id=:Id", map[string]interface{}{"Id": 1}) if err != nil { log.Println(err) return } log.Println(deleteMapResult.RowsAffected())
修改
Sqlx对修改的支持和删除差不多:
updateResult := db.MustExec("Update Person set City=?, UpdateTime=? where Id=?", "Shanghai", time.Now(), 1) log.Println(updateResult.RowsAffected()) updateMapResult, err := db.NamedExec("Update Person set City=:City, UpdateTime=:UpdateTime where Id=:Id", map[string]interface{}{"City": "Chong Qing", "UpdateTime": time.Now(), "Id": 1}) if err != nil { log.Println(err) } log.Println(updateMapResult.RowsAffected())
查询
Sqlx对查询的支持比较多。
使用Get方法查询一条:
getPerson := &Person{} db.Get(getPerson, "select * from Person where Name=?", "Zhang San")
使用Select方法查询多条:
selectPersons := []Person{} db.Select(&selectPersons, "select * from Person where Name=?", "Zhang San")
只查询部分字段:
getId := new(int64) db.Get(getId, "select Id from Person where Name=?", "Zhang San") selectTowFieldSlice := []Person{} db.Select(&selectTowFieldSlice, "select Id,Name from Person where Name=?", "Zhang San") selectNameSlice := []string{} db.Select(&selectNameSlice, "select Name from Person where Name=?", "Zhang San")
从上可以看出如果只查询部分字段,还可以继续使用struct;特别的只查询一个字段时,使用基本数据类型就可以了。
相关阅读 >>
sql server 2008中的代码安全(八)透明加密(tde)
更多相关阅读请进入《sql》频道 >>

数据库系统概念 第6版
机械工业出版社
本书主要讲述了数据模型、基于对象的数据库和XML、数据存储和查询、事务管理、体系结构等方面的内容。
转载请注明出处:木庄网络博客 » go第三方库sqlx操作MySQL及ORM原理
相关推荐
评论
管理员已关闭评论功能...