Mysql 如何在Revel Controller中访问Gorm?
让我先说这是我在围棋中玩的头几天 我尝试将Revel框架与Gorm一起使用,如下所示:Mysql 如何在Revel Controller中访问Gorm?,mysql,go,go-gorm,revel,Mysql,Go,Go Gorm,Revel,让我先说这是我在围棋中玩的头几天 我尝试将Revel框架与Gorm一起使用,如下所示: package controllers import "github.com/revel/revel" func init() { revel.OnAppStart(InitDB) // maybe some other init things } app/controllers/gorm.go package controllers import ( "fmt" "g
package controllers
import "github.com/revel/revel"
func init() {
revel.OnAppStart(InitDB)
// maybe some other init things
}
app/controllers/gorm.go
package controllers
import (
"fmt"
"go-testapp/app/models"
_ "github.com/go-sql-driver/mysql"
"github.com/jinzhu/gorm"
"github.com/revel/revel"
)
var DB gorm.DB
func InitDB() {
var err error
DB, err = gorm.Open("mysql", "root:@/go-testapp?charset=utf8&parseTime=True")
if err != nil {
panic(err)
}
DB.LogMode(true)
DB.AutoMigrate(models.User{})
}
type GormController struct {
*revel.Controller
DB *gorm.DB
}
package controllers
import (
"fmt"
"go-bingo/app/models"
_ "github.com/go-sql-driver/mysql"
"github.com/revel/revel"
)
type App struct {
GormController
}
func (c App) Index() revel.Result {
user := models.User{Name: "Jinzhu", Age: 18}
fmt.Println(c.DB)
c.DB.NewRecord(user)
c.DB.Create(&user)
return c.RenderJson(user)
}
app/controller/app.go
package controllers
import (
"fmt"
"go-testapp/app/models"
_ "github.com/go-sql-driver/mysql"
"github.com/jinzhu/gorm"
"github.com/revel/revel"
)
var DB gorm.DB
func InitDB() {
var err error
DB, err = gorm.Open("mysql", "root:@/go-testapp?charset=utf8&parseTime=True")
if err != nil {
panic(err)
}
DB.LogMode(true)
DB.AutoMigrate(models.User{})
}
type GormController struct {
*revel.Controller
DB *gorm.DB
}
package controllers
import (
"fmt"
"go-bingo/app/models"
_ "github.com/go-sql-driver/mysql"
"github.com/revel/revel"
)
type App struct {
GormController
}
func (c App) Index() revel.Result {
user := models.User{Name: "Jinzhu", Age: 18}
fmt.Println(c.DB)
c.DB.NewRecord(user)
c.DB.Create(&user)
return c.RenderJson(user)
}
运行后,会导致:
运行时错误:第19行c.DB.NewRecord(用户)
它使用automigrate成功地创建了数据表,但我不知道应该如何在控制器中使用Gorm
有没有正确的提示?您的错误是由于您没有初始化c.DB数据库变量而导致的,它仍然为零
在controllers/init.go文件中,确保您正在调用revel.OnAppStart(InitDB)。它应该是这样的:
package controllers
import "github.com/revel/revel"
func init() {
revel.OnAppStart(InitDB)
// maybe some other init things
}
重要提示
它只是一个替代品。它也有一些起源的陷阱。这个答案可以作为原答案的替代品。但这并不能解决陷阱
请看一看这个非答案的评论,它解决了陷阱
我建议您使用@MaxGabriel的解决方案来保护您的应用程序免受某些类型的慢速DDoS攻击。并降低(在某些情况下)DB压力
原始答案
,您必须调用InitDB
内部的init
函数(进入controllers
包)
这里的完整示例(太多):
树
/app
/控制器
app.go
gorm.go
开始
/模型
user.go
[...]
user.go
//模型/user.go
包装模型
导入“时间”//如果需要/想要
键入用户结构{//示例用户字段
Id int64
名称字符串
加密密码[]字节
密码字符串`sql:“-”`
时间,时间
时间到了,时间到了
DeletedAt time.time//用于软删除
}
gorm.go
//控制器/gorm.go
包控制器
进口(
“github.com/jinju/gorm”
_“github.com/lib/pq”//my-example for postgres
//狂欢的简称
r“github.com/revel/revel”
//你的应用程序名称
“yourappname/app/models”
“数据库/sql”
)
//类型:带有“*gorm.DB”的revel控制器`
//c.Txn将保留'Gdb*gorm.DB`
类型GormController结构{
*r、 控制器
Txn*gorm.DB
}
//它可以用于工作
变量Gdb*gorm.DB
//初始化数据库
func InitDB(){
变量错误
//开放数据库
Gdb,err=gorm.Open(“postgres”,“user=uname dbname=udbname sslmode=disable password=supersecret”)
如果错误!=零{
r、 错误。Println(“致命”,错误)
恐慌(错误)
}
Gdb.AutoMigrate(&models.User{})
//如果需要,请使用唯一索引
//Gdb.Model(&models.User{}).AddUniqueIndex(“idx_User_name”,“name”)
}
//交易
//此方法在每次事务之前填充c.Txn
func(c*GormController)Begin()r.结果{
txn:=Gdb.Begin()
如果txn.错误!=nil{
死机(txn.错误)
}
c、 Txn=Txn
归零
}
//此方法在每次事务处理后清除c.Txn
func(c*GormController)Commit()r.结果{
如果c.Txn==nil{
归零
}
c、 Txn.Commit()
如果err:=c.Txn.Error;err!=nil&&err!=sql.ErrTxDone{
恐慌(错误)
}
c、 Txn=零
归零
}
//此方法也会在每次事务处理后清除c.Txn
func(c*GormController)回滚()r.结果{
如果c.Txn==nil{
归零
}
c、 Txn.Rollback()
如果err:=c.Txn.Error;err!=nil&&err!=sql.ErrTxDone{
恐慌(错误)
}
c、 Txn=零
归零
}
应用程序运行
包控制器
进口(
“github.com/revel/revel”
“yourappname/app/models”
)
类型App struct{
戈尔姆控制器
}
函数(c应用程序)索引()相关结果{
用户:=模型。用户{Name:“jinhup”}
c、 Txn.NewRecord(用户)
c、 Txn.Create(&user)
返回c.RenderJSON(用户)
}
init.go
包控制器
导入“github.com/revel/revel”
func init(){
revel.OnAppStart(InitDB)//在之前调用InitDB函数
revel.InterceptMethod((*GormController.Begin,revel.BEFORE)
revel.InterceptMethod((*GormController.Commit,revel.AFTER)
revel.InterceptMethod((*GormController.Rollback,revel.FINALLY)
}
正如你所看到的,这就像Revel为GORM修改了预订一样
对我来说很好。结果:
{
“Id”:5,
“姓名”:“金珠”,
“EncryptedPassword”:空,
“密码”:“,
“CreatedAt”:“2014-09-22T17:55:14.828661062+04:00”,
“更新日期”:“2014-09-22T17:55:14.828661062+04:00”,
“删除数据”:“0001-01-01T00:00:00Z”
}
或者您需要传入指向AutoMigrate的指针
DB.AutoMigrate(&models.User{})
根据@IvanBlack的建议,这个答案来自他的答案。他的版本是Revel示例代码的直接翻译,但是我们发现了这个答案修复的原始代码中的一些问题。它的主要变化是:
整个HTTP请求不再由数据库事务包装。包装整个HTTP请求会使事务保持打开状态的时间远远超过必要的时间,这可能会导致许多问题:
- 您的事务将在数据库上持有锁,许多持有锁的事务可能会导致死锁
- 使用了更多的数据库资源
- 如果您的HTTP请求主要不受SQL数据库访问的限制,那么这些问题将被放大。例如,如果您的HTTP请求在发出外部HTTP请求或访问另一个数据库时阻塞30秒,则这些服务的速度减慢可能会影响您的SQL数据库
由于在HTTP请求结束时不再自动检查事务是否存在错误,因此在插入数据库时会立即检查错误。这也更正确:想象一下