worm提供了Session方法用于创建带配置的会话。使用会话可以共用一组配置,例如:开启SQL预编译,或者是SQL日志输出配置。另外若要开启事务,则必须创建一个会话。
会话应当只用于一个go routine中, 通常在一个HTTP处理器中创建并使用会话。例如:
func AddOrder(c *wego.WebContext) {
session := worm.NewSession()
session.ShowLog(true)
var order dao.Order
order.Create_time = time.Now().Unix()
//.....
var err error
order.Id, err = dbs.Model(&order).Insert()
if err != nil {
log.Error(err)
c.AbortWithText(510, err.Error())
return
}
c.WriteTextF(200, "%d", order.Id)
}
当使用事务处理时,需要创建 Session对象,并开启数据库事务。在进行事务处理时,在事务中可以混用Struct映射、原生SQL以及SQLBuilder来访问数据库:
func demoTxCommit() {
tx := worm.NewSession()
tx.TxBegin()
var user = User{Name:"name1", Age: 21, Created: time.Now()}
id, err := tx.Model(&user).Insert()
if err != nil{
tx.TxRollback()
return
}
_, err = tx.Table("users").Value("age", 20).Value("name", "zhangsan").Where("id=?", id).Update()
if err != nil{
tx.TxRollback()
return
}
_, err = tx.SQL("delete from users where id=?", id).Exec()
if err != nil{
tx.TxRollback()
return
}
tx.TxCommit()
}
worm支持SQL语句的预编译,使用SQL语句预编译可以提升数据库访问的效率。在worm中可以通过三种方式开启SQL语句预编译:全局开启、会话中开启、语句中开启。
func main2() {
dbcnn, err := initMySql("account:pwd@tcp(127.0.0.1:3306)/db?charset=utf8&parseTime=True")
if err != nil {
log.Error(err)
}
defer dbcnn.Close()
err = worm.InitMysql(dbcnn)
if err != nil {
log.Error(err)
return
}
worm.ShowSqlLog(true)
//开启SQL语句预编译
worm.UsePrepare(true)
//设置预编译stmt缓存的最大数量
worm.SetMaxStmtCacheNum(1000)
}
func demoPrepareSession() {
session := worm.NewSession()
session.UsePrepare(true)
var user = User{Name:"name1", Age: 21, Created: time.Now()}
id, err := worm.Model(&user).Insert()
if err != nil{
log.Error(err)
return
}
_, err = worm.Model(&User{}).ID(id).Delete()
if err != nil{
log.Error(err)
return
}
}
func demoModelPrepare() {
var user = User{Name:"name1", Age: 21, Created: time.Now()}
_, err := worm.Model(&user).UsePrepare(true).Select("name", "age").ID(1).Update()
if err != nil{
log.Error(err)
return
}
}
钩子是在创建、查询、更新、删除等操作之前、之后调用的函数。如果您为模型定义了指定的钩子,它会在创建、更新、查询、删除时自动被调用。worm提供了以下钩子:
BeforeInsert(ctx context.Context)
AfterInsert(ctx context.Context)
BeforeUpdate(ctx context.Context)
AfterUpdate(ctx context.Context)
BeforeDelete(ctx context.Context)
AfterDelete(ctx context.Context)
BeforeQuery(ctx context.Context)
AfterQuery(ctx context.Context)
以下代码时添加了BeforeQuery钩子以及AfterQuery钩子的实体类:
type User struct {
Id int64 `db:"id;autoincr"`
Name string `db:"name"`
Age int64 `db:"age"`
Passwd string `db:"passwd"`
Created time.Time `db:"created;n_update"`
}
func (ent *User) TableName() string {
return "user"
}
func (ent *User)BeforeQuery(ctx context.Context) {
fmt.Println("User.BeforeQuery")
if ctx != nil {
fmt.Println(ctx.Value("test_key"))
}
}
func (ent *User)AfterQuery(ctx context.Context) {
fmt.Println("User.AfterQuery")
if ctx != nil {
fmt.Println(ctx.Value("test_key"))
}
}
worm缺省开启了SQL日志的输出,SQL日志的输出可以让您定位sql语句中的bug,也可以通过SQL日志来获取sql语句执行的性能。以下是SQL日志的例子:
[SQL] insert into user set name='NameVo',age=31
[RET] DB: time=36.202ms insertId=273
[SQL] update user set name='NameVo2',age=32 where id=273
[RET] DB: time=22.935ms affected=1
[SQL] select id,name,age from user where id=273 limit 1
[RET] DB: time=52.792ms
[SQL] select id,name,age from user where id>0
[RET] DB: time=19.891ms
说明:
sql语句:sql语句会转换为便于阅读的形式。
DB/TX:用于说明没有开启事务。
time:是执行sql语句的时间。
worm.ShowSqlLog(false)
若您希望使用自定义的日志记录器来输出日志,您可以实现SQL日志回调函数,SQL日志回调函数的定义如下:
type SqlPrintCB func(ctx *LogContex)
例如:
func print_sql_log(ctx *worm.LogContex) {
log.Println(ctx.GetPrintSQL())
log.Println(ctx.GetPrintResult())
}
另外需要为worm开启SQL日志的输出,以及指定SQL日志回调函数:
worm.ShowSqlLog(true)
worm.SetSqlLogCB(print_sql_log)