golang sqlx mysql_gosql: 基于sqlx封装的golang数据库操作

gosql是一个基于sqlx的简单数据库操作包,已更新到V2版。它移除了Model和Table函数的第二个参数,用WithTx(tx)代替,删除了Model接口的DbName()函数,统一了API设计规范。文章介绍了如何连接数据库、使用基本的SQL操作、结构体映射、事务处理以及钩子函数等。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

gosql

The package based on sqlx, It's simple and keep simple

badge.svg

badge.svg

gosql

gosql?status.svg

mit.svg?v=103

⚠️ Because of some disruptive changes, The current major version is upgraded to V2,If you continue with V1, you can check out the v1 branches https://github.com/ilibs/gosql/tree/v1

V2 ChangeLog

Remove the second argument to the Model() and Table() functions and replace it with WithTx(tx)

Remove Model interface DbName() function,use the Use() function

Uniform API design specification, see APIDESIGN

Relation add connection:"db2" struct tag, Solve the cross-library connection problem caused by deleting DbName()

Discard the WithTx function

Usage

Connection database and use sqlx original function,See the https://github.com/jmoiron/sqlx

import (

_ "github.com/go-sql-driver/mysql" //mysql driver

"github.com/ilibs/gosql/v2"

)

func main(){

configs := make(map[string]*gosql.Config)

configs["default"] = &gosql.Config{

Enable: true,

Driver: "mysql",

Dsn: "root:123456@tcp(127.0.0.1:3306)/test?charset=utf8&parseTime=True&loc=Asia%2FShanghai",

ShowSql: true,

}

//connection database

gosql.Connect(configs)

gosql.QueryRowx("select * from users where id = 1")

}

Use default database, So you can use wrapper function

//Exec

gosql.Exec("insert into users(name,email,created_at,updated_at) value(?,?,?,?)","test","test@gmail.com",time.Now(),time.Now())

//Queryx

rows,err := gosql.Queryx("select * from users")

for rows.Next() {

user := &Users{}

err = rows.StructScan(user)

}

rows.Close()

//QueryRowx

user := &Users{}

err := gosql.QueryRowx("select * from users where id = ?",1).StructScan(user)

//Get

user := &Users{}

err := gosql.Get(user,"select * from users where id = ?",1)

//Select

users := make([]*Users)

err := gosql.Select(&users,"select * from users")

//Change database

db := gosql.Use("test")

db.Queryx("select * from tests")

You can also set the default database connection name

gosql.SetDefaultLink("log")

gosql.Connect(configs)

gosql.Get etc., will use the configuration with the connection name log

Using struct

type Users struct {

Id int `db:"id"`

Name string `db:"name"`

Email string `db:"email"`

Status int `db:"status"`

CreatedAt time.Time `db:"created_at"`

UpdatedAt time.Time `db:"updated_at"`

}

func (u *Users) TableName() string {

return "users"

}

func (u *Users) PK() string {

return "id"

}

//Get

user := &Users{}

gosql.Model(user).Where("id=?",1).Get()

//All

user := make([]*Users,0)

gosql.Model(&user).All()

//Create and auto set CreatedAt

gosql.Model(&User{Name:"test",Email:"test@gmail.com"}).Create()

//Update

gosql.Model(&User{Name:"test2",Email:"test@gmail.com"}).Where("id=?",1).Update()

//If you need to update the zero value, you can do so

gosql.Model(&User{Status:0}).Where("id=?",1).Update("status")

//Delete

gosql.Model(&User{}).Where("id=?",1).Delete()

If you use struct to generate where conditions

//Get where id = 1 and name = "test1"

user := &Users{Id:1,Name:"test1"}

gosql.Model(&user).Get()

//Update default use primary key as the condition

gosql.Model(&User{Id:1,Name:"test2"}).Update()

//Use custom conditions

//Builder => UPDATE users SET `id`=?,`name`=?,`updated_at`=? WHERE (status = ?)

gosql.Model(&User{Id:1,Name:"test2"}).Where("status = ?",1).Update()

//Delete

gosql.Model(&User{Id:1}).Delete()

But the zero value is filtered by default, you can specify fields that are not filtered. For example

user := &Users{Id:1,Status:0}

gosql.Model(&user).Get("status")

You can use the genstruct tool to quickly generate database structs

Transaction

The Tx function has a callback function, if an error is returned, the transaction rollback

gosql.Tx(func(tx *gosql.DB) error {

for id := 1; id < 10; id++ {

user := &Users{

Id: id,

Name: "test" + strconv.Itoa(id),

Email: "test" + strconv.Itoa(id) + "@test.com",

}

//v2 support, do some database operations in the transaction (use 'tx' from this point, not 'gosql')

tx.Model(user).Create()

if id == 8 {

return errors.New("interrupt the transaction")

}

}

//query with transaction

var num int

err := tx.QueryRowx("select count(*) from user_id = 1").Scan(&num)

if err != nil {

return err

}

return nil

})

If you need to invoke context, you can use gosql.Txx

Now support gosql.Begin() or gosql.Use("other").Begin() for example:

tx, err := gosql.Begin()

if err != nil {

return err

}

for id := 1; id < 10; id++ {

_, err := tx.Exec("INSERT INTO users(id,name,status,created_at,updated_at) VALUES(?,?,?,?,?)", id, "test"+strconv.Itoa(id), 1, time.Now(), time.Now())

if err != nil {

return tx.Rollback()

}

}

return tx.Commit()

Automatic time

If your fields contain the following field names, they will be updated automatically

AUTO_CREATE_TIME_FIELDS = []string{

"create_time",

"create_at",

"created_at",

"update_time",

"update_at",

"updated_at",

}

AUTO_UPDATE_TIME_FIELDS = []string{

"update_time",

"update_at",

"updated_at",

}

Using Map

Create Update Delete Count support map[string]interface,For example:

//Create

gosql.Table("users").Create(map[string]interface{}{

"id": 1,

"name": "test",

"email": "test@test.com",

"created_at": "2018-07-11 11:58:21",

"updated_at": "2018-07-11 11:58:21",

})

//Update

gosql.Table("users").Where("id = ?", 1).Update(map[string]interface{}{

"name": "fifsky",

"email": "fifsky@test.com",

})

//Delete

gosql.Table("users").Where("id = ?", 1).Delete()

//Count

gosql.Table("users").Where("id = ?", 1).Count()

//Change database

gosql.Use("db2").Table("users").Where("id = ?", 1).Count()

//Transaction `tx`

tx.Table("users").Where("id = ?", 1}).Count()

sql.Null*

Now Model support sql.Null* field's, Note, however, that if sql.Null* is also filtered by zero values,For example

type Users struct {

Id int `db:"id"`

Name string `db:"name"`

Email string `db:"email"`

Status int `db:"status"`

SuccessTime sql.NullString `db:"success_time" json:"success_time"`

CreatedAt time.Time `db:"created_at" json:"created_at"`

UpdatedAt time.Time `db:"updated_at" json:"updated_at"`

}

user := &Users{

Id: 1,

SuccessTime: sql.NullString{

String: "2018-09-03 00:00:00",

Valid: false,

}

}

err := gosql.Model(user).Get()

Builder SQL:

Query: SELECT * FROM users WHERE (id=?);

Args: []interface {}{1}

Time: 0.00082s

If sql.NullString of Valid attribute is false, SQL builder will ignore this zero value

gosql.Expr

Reference GORM Expr, Resolve update field self-update problem

gosql.Table("users").Update(map[string]interface{}{

"id":2,

"count":gosql.Expr("count+?",1)

})

//Builder SQL

//UPDATE `users` SET `count`=count + ?,`id`=?; [1 2]

"In" Queries

Because database/sql does not inspect your query and it passes your arguments directly to the driver, it makes dealing with queries with IN clauses difficult:

SELECT * FROM users WHERE level IN (?);

sqlx.In is encapsulated In gosql and can be queried using the following schema

var levels = []int{4, 6, 7}

rows, err := gosql.Queryx("SELECT * FROM users WHERE level IN (?);", levels)

//or

user := make([]*Users, 0)

err := gosql.Select(&user, "select * from users where id in(?)",[]int{1,2,3})

Relation

gosql used the golang structure to express the relationships between tables,You only need to use the relation Tag to specify the associated field, see example

⚠️ Since version v2, the relation query across library connections needs to be specified using connection tag

type MomentList struct {

models.Moments

User *models.Users `json:"user" db:"-" relation:"user_id,id"` //one-to-one

Photos []*models.Photos `json:"photos" db:"-" relation:"id,moment_id" connection:"db2"` //one-to-many

}

Get single result

moment := &MomentList{}

err := gosql.Model(moment).Where("status = 1 and id = ?",14).Get()

//output User and Photos and you get the result

SQL:

2018/12/06 13:27:54

Query: SELECT * FROM `moments` WHERE (status = 1 and id = ?);

Args: []interface {}{14}

Time: 0.00300s

2018/12/06 13:27:54

Query: SELECT * FROM `moment_users` WHERE (id=?);

Args: []interface {}{5}

Time: 0.00081s

2018/12/06 13:27:54

Query: SELECT * FROM `photos` WHERE (moment_id=?);

Args: []interface {}{14}

Time: 0.00093s

Get list result, many-to-many

var moments = make([]*MomentList, 0)

err := gosql.Model(&moments).Where("status = 1").Limit(10).All()

//You get the total result for *UserMoment slice

SQL:

2018/12/06 13:50:59

Query: SELECT * FROM `moments` WHERE (status = 1) LIMIT 10;

Time: 0.00319s

2018/12/06 13:50:59

Query: SELECT * FROM `moment_users` WHERE (id in(?));

Args: []interface {}{[]interface {}{5}}

Time: 0.00094s

2018/12/06 13:50:59

Query: SELECT * FROM `photos` WHERE (moment_id in(?, ?, ?, ?, ?, ?, ?, ?, ?, ?));

Args: []interface {}{[]interface {}{1, 2, 3, 4, 5, 6, 7, 8, 9, 10}}

Time: 0.00087s

Relation Where:

moment := &MomentList{}

err := gosql.Relation("User" , func(b *gosql.ModelStruct) {

//this is builder instance,

b.Where("gender = 0")

}).Get(moment , "select * from moments")

Hooks

Hooks are functions that are called before or after creation/querying/updating/deletion.

If you have defiend specified methods for a model, it will be called automatically when creating, updating, querying, deleting, and if any callback returns an error, gosql will stop future operations and rollback current transaction.

// begin transaction

BeforeChange

BeforeCreate

// update timestamp `CreatedAt`, `UpdatedAt`

// save

AfterCreate

AfterChange

// commit or rollback transaction

Example:

func (u *Users) BeforeCreate() (err error) {

if u.IsValid() {

err = errors.New("can't save invalid data")

}

return

}

func (u *Users) AfterCreate(tx *gosql.DB) (err error) {

if u.Id == 1 {

u.Email = "after@test.com"

tx.Model(u).Update()

}

return

}

BeforeChange and AfterChange only used in create/update/delete

All Hooks:

BeforeChange

AfterChange

BeforeCreate

AfterCreate

BeforeUpdate

AfterUpdate

BeforeDelete

AfterDelete

BeforeFind

AfterFind

Hook func type supports multiple ways:

func (u *Users) BeforeCreate()

func (u *Users) BeforeCreate() (err error)

func (u *Users) BeforeCreate(tx *gosql.DB)

func (u *Users) BeforeCreate(tx *gosql.DB) (err error)

Thanks

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值