introduce
1.1 Introduction
Full function ORM Related (Has One,Has Many,Belongs To,Many To Many,Polymorphic,Single table inheritance) Create,Save,Update,Delete,Find Hook method support Preload、Joins Preloading Transactions,嵌套Transactions,Save Point,Rollback To Saved Point Context,Precompiled mode,DryRun model Batch Insert,FindInBatches,Find/Create with Map,use SQL expression、Context Valuer conduct CRUD SQL Builder,Upsert,Database lock,Optimizer/Index/Comment Hint,Named Parameters,Subquery Compound primary key,index,constraint Auto Migration Customize Logger Flexible extensible plug-ins API:Database Resolver(Multi-database,Read and write separation)、Prometheus… Each feature has been tested Developer friendly
1.2 Installation
go get -u /gorm go get -u /driver/sqlite
2. Use
2.1 Create a table
package main import ( "fmt" "/driver/mysql" "/gorm" ) //Model Structuretype Student struct { Id int Name string Age int } type User struct { Name string `gorm:"type:varchar(20);not null"` Telephone string `gorm:"varchar(110;not null;unique"` Password string `gorm:"size:255;not null"` } func main() { // Use dsn to connect to the database, the database pool comes with Grom //Account: Password@Connection method (ip address: port number)/Database? Language, time zone (8-hour system is adopted if the time zone is not set) dsn := "root:mysql@tcp(127.0.0.1:3306)/gotest?charset=utf8mb4&parseTime=True&loc=Local" conn, err := ((dsn), &{}) //Use mysq to connect to the database, the second parameter can add more configuration (optional) if err != nil { (err) } (&Student{}) //Create a table? Determine whether the table structure exists} //Multi-table creation(&Company{}, &Worker{})
2.2. Add data
stu := &Student{ Id: 3, Name: "li333", Age: 30, } res := (stu) //Insert data into the database, its return value has only one type, no error type //Note: If the above is written as stu := Student{...}, then it is written as Create(&stu) if != nil { //Add to determine whether the data is inserted? () }
2.3. Query data
var student Student //Query First query one (&student) (student) () //Condition query res := (&student, "name=? and id=?", "yang", 1) (res) //Query all Find var stu []Student ("students").Find(&stu) for _, v := range stu { () } // IN var students []Student ("students").Where("name IN ?", []string{"abc", "bili"}).Find(&students) (students) // LIKE ("name LIKE ?", "%jin%").Find(&users) // AND ("name = ? AND age >= ?", "jinzhu", "22").Find(&users) // Time ("updated_at > ?", (2022,05,20,0,0,0,0,&{})).Find(&users) // BETWEEN ("created_at BETWEEN ? AND ?", (2022,05,20,0,0,0,0,&{}), ()).Find(&users)
2.4 Update data
//Update data ("students").Where("id=?", 1).Update("name", "ttt") ("students").Where("id=?", 2).Updates(&Student{Name: "bili", Age: 10}) //Press the primary key to update, pass in the structure object, and update the corresponding content according to the corresponding primary key ("user").Save(&user1)
2.5 Delete data
("students").Where("id=?", 1).Delete(&Student{})
2.6 Execute native sql
("select * from students where id=?", 3).Scan(&student) (student) ("DROP TABLE users") ("UPDATE orders SET shipped_at=? WHERE id IN ?", (), []int64{1,2,3})
3. One-to-one
3.1 Create a table
package main import ( "fmt" "/driver/mysql" "/gorm" ) type User struct { CreditCard CreditCard Name string } type CreditCard struct { Number string UserID uint } func main() { // Use dsn to connect to the database, the database pool comes with Grom //Account: Password@Connection method (ip address: port number)/Database? Language, time zone (8-hour system is adopted if the time zone is not set) dsn := "root:mysql@tcp(127.0.0.1:3306)/crow?charset=utf8mb4&parseTime=True&loc=Local" conn, err := ((dsn), &{}) //Use mysq to connect to the database, the second parameter can add more configuration (optional) if err != nil { (err) } (&User{}) (&CreditCard{}) //Create a table? Determine whether the table structure exists user := &User{ Name: "Li Si", } (user) card := &CreditCard{ Number: "123", UserID: 1, } (card) }
3.2 Polymorphic association
//Polymorphic association//GORM provides polymorphic association support for has one and has many, which saves the table name and primary key value of the owner entity into fields of polymorphic type. type Cat struct { ID int Name string Toy Toy `gorm:"polymorphic:Owner;"` } type Dog struct { ID int Name string Toy Toy `gorm:"polymorphic:Owner;"` } type Toy struct { ID int Name string OwnerID int OwnerType string } (&Dog{Name: "dog1", Toy: Toy{Name: "toy1"}}) // INSERT INTO `dogs` (`name`) VALUES ("dog1") // INSERT INTO `toys` (`name`,`owner_id`,`owner_type`) VALUES ("toy1","1","dogs")
3.3 Foreign Key Constraints
You can use the tagconstraint
ConfigurationOnUpdate
、OnDelete
Implement foreign key constraints, which are created when migrating using GORM, for example:
type User struct { Name string CompanyID int Company Company `gorm:"constraint:OnUpdate:CASCADE,OnDelete:SET NULL;"` } type Company struct { ID int Name string }
4. One-to-many
Has Many
has many establish a one-to-many connection with another model. Unlike has one, owners can have zero or more correlation models.
For example, your application contains user and credit card models, and each user can have multiple credit cards.
// User has multiple CreditCards, UserID is a foreign keytype User struct { CreditCards []CreditCard } type CreditCard struct { Number string UserID uint }
package main import ( "fmt" "/driver/mysql" "/gorm" ) type User struct { MemberNumber string `gorm:"varchar(110;not null;unique"` CreditCards []CreditCard `gorm:"foreignKey:UserNumber;references:MemberNumber"` Name string } type CreditCard struct { Number string UserNumber string `gorm:"varchar(110;not null;unique"` } func main() { // Use dsn to connect to the database, the database pool comes with Grom //Account: Password@Connection method (ip address: port number)/Database? Language, time zone (8-hour system is adopted if the time zone is not set) dsn := "root:mysql@tcp(127.0.0.1:3306)/crow?charset=utf8mb4&parseTime=True&loc=Local" conn, err := ((dsn), &{}) //Use mysq to connect to the database, the second parameter can add more configuration (optional) if err != nil { (err) } (&User{}, &CreditCard{}) user := User{ Name: "ttt3", MemberNumber: "1003", } (&user) card := CreditCard{ Number: "111", UserNumber: , } (&card) }
5. Many-to-many
Many To Many
Many to Many will add a join table to both models.
For example, your application includes user and language, and one user can say multiple languages, and multiple users can also say one language.
// User owns and belongs to multiple languages, `user_languages` is the connection tabletype User struct { Languages []Language `gorm:"many2many:user_languages;"` } type Language struct { Name string }
When using GORMAutoMigrate
forUser
When creating a table, GORM automatically creates the connection table
Backreferences
// User owns and belongs to multiple languages, `user_languages` is the connection tabletype User struct { Languages []*Language `gorm:"many2many:user_languages;"` } type Language struct { Name string Users []*User `gorm:"many2many:user_languages;"` }
Rewrite foreign keys
formany2many
Relationship, joining tables will have foreign keys for two models at the same time, for example:
type User struct { Languages []Language `gorm:"many2many:user_languages;"` } type Language struct { Name string } // Join Table: user_languages // foreign key: user_id, reference: // foreign key: language_id, reference:
To rewrite them, you can use the tagsforeignKey
、reference
、joinforeignKey
、joinReferences
. Of course, you don't need to use all tags, you can only use one of the foreign keys and references to rewrite the part.
type User struct { Profiles []Profile `gorm:"many2many:user_profiles;foreignKey:Refer;joinForeignKey:UserReferID;References:UserRefer;JoinReferences:UserRefer"` Refer uint } type Profile struct { Name string UserRefer uint } // The connection table will be created: user_profiles// foreign key: user_refer_id, reference: // foreign key: profile_refer, reference: profiles.user_refer
Self-cited Many2Many
Self-cited many2many relationship
type User struct { Friends []*User `gorm:"many2many:user_friends"` } // The connection table will be created: user_friends// foreign key: user_id, reference: // foreign key: friend_id, reference:
6. Obtain multi-table data
Preload
GORM allowsPreload
Other SQL directly load relationships, such as:
type User struct { Username string Orders []Order } type Order struct { UserID uint Price float64 } // Preload related Order when searching for user("Orders").Find(&users) // SELECT * FROM users; // SELECT * FROM orders WHERE user_id IN (1,2,3,4); ("Orders").Preload("Profile").Preload("Role").Find(&users) // SELECT * FROM users; // SELECT * FROM orders WHERE user_id IN (1,2,3,4); // has many // SELECT * FROM profiles WHERE user_id IN (1,2,3,4); // has one // SELECT * FROM roles WHERE id IN (4,5,6); // belongs to
Joins Preload
Preload
Load associated data in a separate query. andJoin Preload
The associated data will be loaded using inner join, for example:
("Company").Joins("Manager").Joins("Account").First(&user, 1) ("Company").Joins("Manager").Joins("Account").First(&user, " = ?", "jinzhu") ("Company").Joins("Manager").Joins("Account").Find(&users, " IN ?", []int{1,2,3,4,5})
Notice
Join Preload
Suitable for one-to-one relationships, for example:has one
,belongs to
Preload all
Used when creating and updatingSelect
similar,Can also be with
Preload
Use together, it can be usedPreload
All associations, for example:
type User struct { Name string CompanyID uint Company Company Role Role } ().Find(&users)
Preload with conditions
GORM allows conditional Preload associations, similar toInline conditions
// Preload Order with conditions("Orders", "state NOT IN (?)", "cancelled").Find(&users) // SELECT * FROM users; // SELECT * FROM orders WHERE user_id IN (1,2,3,4) AND state NOT IN ('cancelled'); ("state = ?", "active").Preload("Orders", "state NOT IN (?)", "cancelled").Find(&users) // SELECT * FROM users WHERE state = 'active'; // SELECT * FROM orders WHERE user_id IN (1,2) AND state NOT IN ('cancelled');
Custom preload SQL
You canfunc(db *) *
Implement custom preload SQL, for example:
("Orders", func(db *) * { return (" DESC") }).Find(&users) // SELECT * FROM users; // SELECT * FROM orders WHERE user_id IN (1,2,3,4) order by DESC;
Nested preload
GORM supports nested preloading, for example:
("").Preload("CreditCard").Find(&users) // Customize the conditions for preloading `Orders`// In this way, GORM will not load mismatched order records("Orders", "state = ?", "paid").Preload("").Find(&users)
This is all about this article about golang Gorm framework. For more related golang Gorm framework content, please search for my previous articles or continue browsing the related articles below. I hope everyone will support me in the future!