Model (Models)-Beego ORM
Original
Beego ORM is a powerful Go language ORM framework. Her inspiration comes mainly from Django ORM and SQLAlchemy.
Currently, the framework is still in development and any changes that could lead to incompatibilities may occur.
Database drivers are supported:
- Mysql:github.com/go-sql-driver/mysql
- Postgresql:github.com/lib/pq
- Sqlite3:github.com/mattn/go-sqlite3
The above database drivers all pass the basic test, but we still need your feedback.
ORM Features:
- Supports all types of Go storage
- Easy to use with a simple CRUD style
- Auto Join Association Table
- Cross-Database compatible queries
- Allow direct use of SQL queries/mappings
- Rigorous and complete testing to ensure the stability and robustness of ORM
Install ORM:
go get github.com/astaxie/beego/orm
How to use ORM
Compared to the standard, now the Models folder to create the model of the object, all about the database operations are in the models, controller calls the method in models.
Models.go:
package mainimport ( "github.com/astaxie/beego/orm" //导入包)//定义 struct和数据表进行映射的type User struct { Id int Name string Profile *Profile `orm:"rel(one)"` // OneToOne relation Post []*Post `orm:"reverse(many)"` // 设置一对多的反向关系}type Profile struct { Id int Age int16 User *User `orm:"reverse(one)"` // 设置一对一反向关系(可选)}type Post struct { Id int Title string User *User `orm:"rel(fk)"` //设置一对多关系 Tags []*Tag `orm:"rel(m2m)"`}type Tag struct { Id int Name string Posts []*Post `orm:"reverse(many)"`}func init() { // 需要在init中注册定义的model orm.RegisterModel(new(User), new(Post), new(Profile), new(Tag))}
Main.go
package mainimport ( "fmt" "github.com/astaxie/beego/orm" _ "github.com/go-sql-driver/mysql" // 只是调用init方法)func init() { orm.RegisterDriver("mysql", orm.DRMySQL) orm.RegisterDataBase("default", "mysql", "root:root@/orm_test?charset=utf8")}func main() { o := orm.NewOrm() o.Using("default") // 默认使用 default,你可以指定为其他数据库 profile := new(Profile) profile.Age = 30 user := new(User) user.Profile = profile user.Name = "slene" fmt.Println(o.Insert(profile)) fmt.Println(o.Insert(user))}
Settings for the database
Currently ORM supports three types of databases, the following are tested driver
Add the driver you need to use in import
import ( _ "github.com/go-sql-driver/mysql" _ "github.com/lib/pq" _ "github.com/mattn/go-sqlite3")
Registerdriver
Three default types of databases
// For version 1.6orm.DRMySQLorm.DRSqliteorm.DRPostgres// < 1.6orm.DR_MySQLorm.DR_Sqliteorm.DR_Postgres
// 参数1 driverName// 参数2 数据库类型// 这个用来设置 driverName 对应的数据库类型// mysql / sqlite3 / postgres 这三种是默认已经注册过的,所以可以无需设置orm.RegisterDriver("mysql", orm.DRMySQL)
RegisterDatabase
The ORM must register an alias for default
the database as the default usage.
ORM uses Golang's own connection pool
//registerdatabase Setting the database connect params. Use the database driver self dataSource args.func registerdatabase (aliasname, drivername, dataSource string, params ... int ) Error {var (err Error DB *sql. DB al *alias) db, err = sql. Open (drivername, DataSource) if err! = Nil {err = FMT. Errorf ("Register db '%s ',%s ', aliasname, err. Error ()) Goto end} al, err = Addaliaswthdb (aliasname, drivername, db) if err! = Nil {goto END } al. DataSource = DataSource Detecttz (AL) for I, V: = range params {switch I {case 0:SETMAXID Leconns (al. Name, V) Case 1:setmaxopenconns (al. Name, v)}}end:if err! = nil {if db! = Nil {db. Close ()} debuglog.println (err. Error ())} return err}
// 参数1 数据库的别名,用来在 ORM 中切换数据库使用// 参数2 driverName// 参数3 对应的链接字符串orm.RegisterDataBase("default", "mysql", "root:root@/orm_test?charset=utf8")// 参数4(可选) 设置最大空闲连接// 参数5(可选) 设置最大数据库连接 (go >= 1.2)maxIdle := 30maxConn := 30orm.RegisterDataBase("default", "mysql", "root:root@/orm_test?charset=utf8", maxIdle, maxConn)
Setmaxidleconns
Set the maximum idle connection for the database based on the alias of the database
orm.SetMaxIdleConns("default", 30)
Setmaxopenconns
Set the maximum database connection for the database based on the alias of the database (Go >= 1.2)
orm.SetMaxOpenConns("default", 30)
Time zone settings
The ORM uses time by default. local time zone
- The time it takes to automatically create an ORM
- Time retrieved from the database converted to ORM local time
You can also make changes if you want.
// 设置为 UTC 时间orm.DefaultTimeLoc = time.UTC
While the ORM is registerdatabase, it gets the time zone used by the database, and then time. Time type access is converted to match the time system to ensure that no error occurs.
Attention:
- Due to the Sqlite3 design, access defaults to UTC time
- When using the Go-sql-driver driver, be aware of the parameter settings
Starting with a version, the drive defaults to UTC time instead of local time, so specify the time zone parameter or all in UTC time
For example:root:root@/orm_test?charset=utf8&loc=Asia%2FShanghai
See Loc/parsetime
Registering the Model
If you use ORM. Queryseter for advanced queries, this is a must.
Conversely, this step is not required if you are using only RAW queries and map structs. You can go to view Raw SQL queries
Registermodel
To register your defined Model, the best design is to have a separate models.go file, which is registered in his init function.
Mini version Models.go
package mainimport "github.com/astaxie/beego/orm"type User struct { Id int Name string}func init(){ orm.RegisterModel(new(User))}
Registermodel can also register multiple model
orm.RegisterModel(new(User), new(Profile), new(Post))
For a detailed struct definition, see the document model definition
Registermodelwithprefix
Use table name prefixes
orm.RegisterModelWithPrefix("prefix_", new(User))
The table name after creation is Prefix_user
Newormwithdb
Sometimes it is necessary to manage connection pooling and database links (e.g., the link pool of Go does not allow two queries to use the same link)
But also want to use ORM query function
var driverName, aliasName string// driverName 是驱动的名称// aliasName 是当前 db 的自定义别名var db *sql.DB...o := orm.NewOrmWithDB(driverName, aliasName, db)
Getdb
Returns *SQL from the registered database. DB object, by default returns the database that is aliased to default.
db, err := orm.GetDB()if err != nil { fmt.Println("get default DataBase")}db, err := orm.GetDB("alias")if err != nil { fmt.Println("get alias DataBase")}
Resetmodelcache
Resets a registered model struct, typically used to write test cases
orm.ResetModelCache()
ORM interface uses
Using ORM's inevitable contact with the Ormer interface, let's familiarize ourselves with
var o Ormero = orm.NewOrm() // 创建一个 Ormer// NewOrm 的同时会执行 orm.BootStrap (整个 app 只执行一次),用以验证模型之间的定义并缓存。
Switching the database, or, for transactional processing, will act on the Ormer object and any queries it makes.
So if you need to switch databases and transactions , do not use globally saved Ormer objects.
Ormer define the ORM InterfaceType Ormer Interface {//read data to model//For example://This would find User by Id Field//U = &user{id:user. ID}//err = Ormer.read (u)//This would find User by UserName field//U = &user{username: "Astaxie", Pass Word: "Pass"}//Err = Ormer.read (U, "UserName") Read (MD interface{}, cols ... string) error//Like Read (), but With ' for UPDATE ' clause, useful in transaction. Some databases is not a support for this feature. Readforupdate (MD interface{}, cols ... string) error//Try to read a row from the database, or insert one if it doesn ' t exist Readorcreate (MD interface{}, col1 string, cols ... string) (bool, int64, error)//INSERT model data to Databa SE//For example://User: = new (user)//id, err = ormer.insert (user)//user must a pointer and Insert W Ill set user ' s PK field Insert (interface{}) (Int64, error)//mysql:insertorupdate (model) or insertorupdate (modeL, "colu=colu+value")//If Colu type is Integer:can use (+-*/), String:convert (Colu, "value")//Postgres:inserto Rupdate (model, "Conflictcolumnname") or insertorupdate (model, "Conflictcolumnname", "colu=colu+value")//if Colu type is Integer:can use (+-*/), String:colu | | "Value" Insertorupdate (MD interface{}, Colconflitandargs ... string) (Int64, error)//insert some models to database Insertmulti (bulk int, MDS interface{}) (Int64, error)//update model to database. Cols set the columns those want to update. Find model by Id (PK) field and update columns specified by fields, if cols was null then update all columns//for EX Ample://User: = User{id:2}//user. Langs = append (user. Langs, "Zh-cn", "en-us")//user. Extra.name = "Beego"//user. Extra.data = "ORM"//num, err = ormer.update (&user, "Langs", "Extra") Update (MD interface{}, cols ... string) ( Int64, error)//delete model in database Delete (MD interface{},cols. String) (Int64, error)//load related models to MD model. Args is limit, offset int and order string. Example://ormer.loadrelated (post, "Tags")//For _,tag: = Range post. Tags{...} ARGS[0] bool true usedefaultrelsdepth; False depth 0//args[0] int loadrelationdepth//args[1] int limit default limit//args[2] int offset Defau Lt offset 0//args[3] String order for example: "-id"//Make sure the relation are defined in model struct tags. Loadrelated (MD interface{}, name string, args ... interface{}) (Int64, error)//create a models to models Queryer For example://Post: = Post{id:4}//ATM: = ORMER.QUERYM2M (&post, "Tags") querym2m (MD interface{}, NA Me string) Querym2mer//Return a queryseter for table operations. Table name can be string or struct. e.g. querytable ("user"), QueryTable (&user{}) or QueryTable ((*user) (nil)), QueryTable (ptrstructortablename interface{}) QueRyseter//Switch to another registered database driver by given name. Using (name string) error//BEGIN TRANSACTION//For example://O: = Neworm ()//ERR: = O.begin ()//. . Err = O.rollback () Begin () error//COMMIT TRANSACTION commit () error//Rollback transaction Rollback ( Error//Return a raw query seter for RAW SQL string. For example://Ormer. Raw ("UPDATE ' user ' SET ' user_name ' =?") WHERE ' user_name ' =? "," Slene "," testing "). Exec ()////Update user testing ' s name to Slene Raw (query string, args ... interface{}) rawseter Driver () Driver }
QueryTable
Incoming table name, or Model object, returns a Queryseter
o := orm.NewOrm()var qs QuerySeterqs = o.QueryTable("user")// 如果表没有定义过,会立刻 panic
Using
Switch to a different database
orm.RegisterDataBase("db1", "mysql", "root:root@/orm_db2?charset=utf8")orm.RegisterDataBase("db2", "sqlite3", "data.db")o1 := orm.NewOrm()o1.Using("db1")o2 := orm.NewOrm()o2.Using("db2")// 切换为其他数据库以后// 这个 Ormer 对象的其下的 api 调用都将使用这个数据库
default
the database is used by default without calling the Using
Raw
Working directly with SQL statements
The Raw function returns a rawseter to manipulate the set SQL statements and parameters
o := NewOrm()var r RawSeterr = o.Raw("UPDATE user SET name = ? WHERE name = ?", "testing", "slene")
Driver
Returns the DB information used by the current ORM
type Driver interface { Name() string Type() DriverType}
orm.RegisterDataBase("db1", "mysql", "root:root@/orm_db2?charset=utf8")orm.RegisterDataBase("db2", "sqlite3", "data.db")o1 := orm.NewOrm()o1.Using("db1")dr := o1.Driver()fmt.Println(dr.Name() == "db1") // truefmt.Println(dr.Type() == orm.DRMySQL) // trueo2 := orm.NewOrm()o2.Using("db2")dr = o2.Driver()fmt.Println(dr.Name() == "db2") // truefmt.Println(dr.Type() == orm.DRSqlite) // true
Debug Mode Print query statement
Simple set Debug to True to print the query statement
There may be performance issues that are not recommended for use in production mode
func main() { orm.Debug = true...
The OS is used by default. Stderr Output Log Information
Change the output to your own IO. Writer
var w io.Writer...// 设置为你的 io.Writer...orm.DebugLog = orm.NewLog(w)