首先明确一点:
xorm
中查询多条数据可以使用Find
方法,Find方法的第一个参数为slice的指针或Map指针
举个例子:
// 错误示例
var person []Person
db.where("age = ?", 18).Find(person) // 错误,得传person的地址,尽管person是指针类型
// 正确示例
var person []Person
db.where("age = ?", 18).Find(&person)
如果以上这点没注意到,那么应结合Find
函数返回的报错信息进行检测,报错信息很重要,能帮助我们排查错误。比如engine.ShowSQL(true)
语句不生效,SQL语句打印不出来,很可能是执行SQL前那个函数报错了。
接下进入正题,先看看下面代码:
type Person struct {
Age int `xorm:"not null"`
Sex string `xorm:"not null"`
}
func GetPerson(db *xorm.Engine, age int) []*Person {
var p []*Person
err := db.Where("age = ?", age).Limit(1).Find(&p)
if err != nil {
fmt.Println(err.Error()) // 很重要,这步错误处理不要省略,帮助定位问题
}
return p
}
func TestGetPerson(t *testing.T) {
db, mock, _ := sqlmock.New()
defer db.Close()
mock.ExpectBegin()
row := sqlmock.NewRows([]string{"age", "sex"}).AddRow(18, "男")
mock.ExpectQuery("^SELECT \\* FROM `person` where age = \\?").WillReturnRows(row)
engine,_ := xorm.NewEngine("mysql", "root:123@/test?charset=utf-8")
engine.ShowSQL(true)
engine.DB().DB = db
p := GetPerson(engine, 18)
fmt.Println(p)
}
上述代码中,GetPerson中报错信息显示:
call to Query ‘SELECT `age`, `sex` FROM `person` WHERE (age = ?) LIMIT 1’ with args [{Name: Ordinal:1 Value:18}], was not expected, next expectation is: ExpectedBegin => expecting database transaction Begin
这段报错表示ExpectQuery
函数中传递的正则语句与实际执行的SQL语句没有匹配,根据这段报错信息或打印出来的SQL语句,应该将正则改为:
mock.ExpectQuery(“SELECT `age`, `sex` FROM `person` WHERE \\(age = \\?\\) LIMIT 1”)
或者再简单一点:
mock.ExpectQuery(“SELECT .* FROM `person`”)
只要正则匹配都行。
上述代码还有一个错误,那就是缺少engine.DB().Begin()
。其实段语句可要可不要,视情况而定。当出现了mock.ExpectBegin()
时,需要加上engine.DB().Begin()
,否则不加。因为这两个语句是相匹配的,默认匹配,就像正则一样。
正确精简的版本:
type Person struct {
Age int `xorm:"not null"`
Sex string `xorm:"not null"`
}
func GetPerson(db *xorm.Engine, age int) []*Person {
var p []*Person
err := db.Where("age = ?", age).Limit(1).Find(&p)
if err != nil {
fmt.Println(err.Error())
}
return p
}
func TestGetPerson(t *testing.T) {
db, mock, _ := sqlmock.New()
defer db.Close()
row := sqlmock.NewRows([]string{"age", "sex"}).AddRow(18, "男")
mock.ExpectQuery("SELECT .* FROM `person`").WillReturnRows(row)
engine,_ := xorm.NewEngine("mysql", "root:123@/test?charset=utf-8")
engine.ShowSQL(true)
engine.DB().DB = db
p := GetPerson(engine, 11)
if len(p) > 0 {
fmt.Println(p[0])
}
}