goal-web/database
goal 框架的数据库组件,当然你也可以在 goal 之外的框架使用他。
目前数据库组件暂时不能使用关联关系,你可以用
WhereExists
来代替
go get github.com/goal-web/database
goal 的脚手架自带了绝大多数开发一个 web 应用的所需要的功能和组件,当然包括了数据库组件。一般情况下,我们只需要在 .env 修改自己的数据库配置即可,添加数据库连接可以 config/database.go
修改 Connections
属性。
默认情况下,config/database.go
配置文件像下面那样,默认添加了 sqlite、MySQL、postgresSql 三个数据库连接的配置
和
Laravel
不同的是,goal 把 redis 配置独立出去了,因为 redis 也是一个独立的模块,不想让 redis 依赖 database
package config
import (
"github.com/goal-web/contracts"
"github.com/goal-web/database"
)
func init() {
configs["database"] = func(env contracts.Env) any {
return database.Config{
Default: env.StringOptional("db.connection", "mysql"),
Connections: map[string]contracts.Fields{
"sqlite": {
"driver": "sqlite",
"database": env.GetString("sqlite.database"),
},
"mysql": {
"driver": "mysql",
"host": env.GetString("db.host"),
"port": env.GetString("db.port"),
"database": env.GetString("db.database"),
"username": env.GetString("db.username"),
"password": env.GetString("db.password"),
"unix_socket": env.GetString("db.unix_socket"),
"charset": env.StringOptional("db.charset", "utf8mb4"),
"collation": env.StringOptional("db.collation", "utf8mb4_unicode_ci"),
"prefix": env.GetString("db.prefix"),
"strict": env.GetBool("db.struct"),
"max_connections": env.GetInt("db.max_connections"),
"max_idles": env.GetInt("db.max_idles"),
},
"pgsql": {
"driver": "postgres",
"host": env.GetString("db.pgsql.host"),
"port": env.GetString("db.pgsql.port"),
"database": env.GetString("db.pgsql.database"),
"username": env.GetString("db.pgsql.username"),
"password": env.GetString("db.pgsql.password"),
"charset": env.StringOptional("db.pgsql.charset", "utf8mb4"),
"prefix": env.GetString("db.pgsql.prefix"),
"schema": env.StringOptional("db.pgsql.schema", "public"),
"sslmode": env.StringOptional("db.pgsql.sslmode", "disable"),
"max_connections": env.GetInt("db.pgsql.max_connections"),
"max_idles": env.GetInt("db.pgsql.max_idles"),
},
},
}
}
}
.env
的数据库相关配置
# 默认连接
db.connection=sqlite
sqlite.database=/Users/qbhy/project/go/goal-web/goal/example/database/db.sqlite
db.host=localhost
db.port=3306
db.database=goal
db.username=root
db.password=password
db.pgsql.host=localhost
db.pgsql.port=55433
db.pgsql.database=postgres
db.pgsql.username=postgres
db.pgsql.password=123456
app/models/user.go
文件
package models
import (
"github.com/goal-web/database/table"
"github.com/goal-web/supports/class"
)
// UserClass 这个类变量,以后大有用处
var UserClass = class.Make(new(User))
// UserModel 返回 table 实例,继承自查询构造器并且实现了所有 future
func UserModel() *table.Table {
return table.Model(UserClass, "users")
}
// User 模型结构体
type User struct {
Id int64 `json:"id"`
NickName string `json:"name"`
}
package tests
import (
"fmt"
"github.com/goal-web/contracts"
"github.com/goal-web/database/table"
"github.com/goal-web/example/models"
"github.com/stretchr/testify/assert"
"testing"
)
func getQuery(name string) contracts.Query[T] {
// 测试用例环境下的简易 goal 应用启动
app := initApp("/Users/qbhy/project/go/goal-web/goal/tests")
//return table.Query("users") 返回 table 实例,使用默认连接
//tx, _ := app.Get("db").(contracts.DBConnection).Begin()
//return table.WithTX("users", tx) // 事物环境下执行
//return table.WithConnection(name, "sqlite") // 返回指定连接的 table 实例,使用连接名
return table.WithConnection(name, app.Get("db").(contracts.DBConnection)) // 也可以指定连接实例
}
// TestTableQuery 测试不带模型的 table 查询,类似 laravel 的 DB::table()
func TestTableQuery(t *testing.T) {
getQuery("users").Delete()
// 不设置模型的情况下,返回 contracts.Fields
user := getQuery("users").Create(contracts.Fields{
"name": "qbhy",
}).(contracts.Fields)
fmt.Println(user)
userId := user["id"].(int64)
// 判断插入是否成功
assert.True(t, userId > 0)
// 获取数据总量
assert.True(t, getQuery("users").Count() == 1)
// 修改数据
num := getQuery("users").Where("name", "qbhy").Update(contracts.Fields{
"name": "goal",
})
assert.True(t, num == 1)
// 判断修改后的数据
user = getQuery("users").Where("name", "goal").First().(contracts.Fields)
err := getQuery("users").Chunk(10, func(collection contracts.Collection, page int) error {
assert.True(t, collection.Len() == 1)
fmt.Println(collection.ToJson())
return nil
})
assert.Nil(t, err)
assert.True(t, user["id"] == userId)
assert.True(t, user["name"] == "goal")
assert.True(t, getQuery("users").Find(userId).(contracts.Fields)["id"] == userId)
assert.True(t, getQuery("users").Where("id", userId).Delete() == 1)
assert.Nil(t, getQuery("users").Find(userId))
}
func TestModel(t *testing.T) {
initApp("/Users/qbhy/project/go/goal-web/goal/tests")
fmt.Println("用table查询:",
getQuery("users").Get().Map(func(user contracts.Fields) {
fmt.Println("用table查询", user)
}).ToJson()) // query 返回 Collection<contracts.Fields>
user := models.UserModel().Create(contracts.Fields{
"name": "qbhy",
}).(models.User)
fmt.Println("创建后返回模型", user)
fmt.Println("用table查询:",
getQuery("users").Get().Map(func(user contracts.Fields) {
fmt.Println("用table查询", user)
}).ToJson()) // query 返回 Collection<contracts.Fields>
// 用模型查询
fmt.Println(models.UserModel(). // model 返回 Collection<models.User>
Get().
Map(func(user models.User) {
fmt.Println("id:", user.Id)
}).ToJson())
fmt.Println(models.UserModel().Where("id", ">", 0).Delete())
}
更多查询构造器用法请移步 goal-web/querybuilder
// TestMysqlDatabaseWithoutApplication 只需要给给 table 包设置一个可用的 contracts.DBFactory 即可正常使用 table 下面的数据库操作方法
func TestMysqlDatabaseWithoutApplication(t *testing.T) {
table.SetFactory(database.NewFactory(database.Config{
Default: "mysql",
Connections: map[string]contracts.Fields{
"mysql": {
"driver": "mysql",
"host": "localhost",
"port": "3306",
"database": "goal",
"username": "root",
"password": "123456",
"charset": "utf8mb4",
"collation": "utf8mb4_unicode_ci",
},
},
}, nil))
assert.True(t, table.Query("users").Count() == 0)
user := table.Query("users").Create(contracts.Fields{
"name": "testing",
})
assert.NotNil(t, user)
assert.True(t, user.(contracts.Fields)["name"] == "testing")
assert.True(t, table.Query("users").Count() == 1)
table.Query("users").Where("name", "testing").Delete()
assert.True(t, table.Query("users").Count() == 0)
}