目录gORMxormgORM安装GORM首先,确保你的环境中已经安装了Go和一个支持的数据库驱动。然后通过以下命令安装gorm:goget-ugorm.io/gorm基础概念Model:数据库中的表。Record:表中的行。Field:表中的列。Relat
首先,确保你的环境中已经安装了Go和一个支持的数据库驱动。然后通过以下命令安装gorm:
go get -u gorm.io/gorm
连接数据库
import (
"gorm.io/driver/sqlite"
"gorm.io/gorm"
)
func main() {
db, err := gorm.Open(sqlite.Open("test.db"), &gorm.Config{})
if err != nil {
panic("failed to connect database")
}
}
创建模型 定义一个简单的用户模型:
type User struct {
gorm.Model
Name string
Email string
}
自动迁移
db.AutoMigrate(&User{})
创建记录
db.Create(&User{Name: "张三", Email: "zhangsan@example.com"})
查询记录
var user User
db.First(&user, 1) // 根据主键查询
示例代码:
type Profile struct {
gorm.Model
UserID uint
User User
}
db.Model(&Profile{}).Association("User").Set(&User{})
批量操作
users := []User{{Name: "李四"}, {Name: "王五"}}
db.Create(&users)
事务处理
tx := db.Begin()
tx.Create(&user)
if tx.Error != nil {
tx.Rollback()
} else {
tx.Commit()
}
例如,用户和其个人资料的关系:
type User struct {
gorm.Model
Name string
Email string
ProfileID uint
Profile Profile `gorm:"foreignKey:ProfileID"`
}
type Profile struct {
gorm.Model
Address string
User User `gorm:"foreignKey:ID"`
}
创建和读取关联数据:
// 创建用户及其个人资料
profile := Profile{Address: "上海市"}
db.Create(&profile)
user := User{Name: "张三", Email: "zhangsan@example.com", ProfileID: profile.ID}
db.Create(&user)
// 读取用户及其个人资料
var user User
db.Preload("Profile").First(&user, 1)
fmt.Println(user.Name, user.Profile.Address)
例如,用户和其文章的关系:
type User struct {
gorm.Model
Name string
Email string
Posts []Post `gorm:"foreignKey:UserID"`
}
type Post struct {
gorm.Model
Title string
UserID uint
User User `gorm:"foreignKey:ID;constraint:OnUpdate:CASCADE,OnDelete:CASCADE;"`
}
创建和读取关联数据:
// 创建用户
user := User{Name: "张三", Email: "zhangsan@example.com"}
db.Create(&user)
// 创建文章并关联用户
post := Post{Title: "我的第一篇文章", UserID: user.ID}
db.Create(&post)
// 读取用户及其所有文章
var user User
db.Preload("Posts").First(&user, 1)
for _, post := range user.Posts {
fmt.Println(post.Title)
}
例如,用户和其关注的用户的关系:
type User struct {
gorm.Model
Name string
Follows []User `gorm:"many2many:follows;"`
}
// 创建用户
user1 := User{Name: "张三"}
user2 := User{Name: "李四"}
db.Create(&user1)
db.Create(&user2)
// 用户1关注用户2
db.Model(&user1).Association("Follows").Append(&user2)
// 读取用户及其关注的用户
var user User
db.Preload("Follows").First(&user, 1)
for _, follow := range user.Follows {
fmt.Println(follow.Name)
}
批量插入和更新数据可以显著提高性能。
批量插入
users := []User{
{Name: "张三", Email: "zhangsan@example.com"},
{Name: "李四", Email: "lisi@example.com"},
{Name: "王五", Email: "wangwu@example.com"},
}
db.Create(&users)
批量更新
db.Model(&User{}).Where("age < ?", 30).Updates(map[string]interface{}{"age": 30})
事务处理可以确保一系列操作要么全部成功,要么全部失败。
db.Transaction(func(tx *gorm.DB) error {
var user User
if err := tx.Where("name = ?", "张三").First(&user).Error; err != nil {
return err
}
if err := tx.Model(&user).Update("age", 30).Error; err != nil {
return err
}
return nil
})
性能优化对于大型应用至关重要。
批处理 批量插入和批量更新可以减少数据库的网络开销。
db.CreateInBatches(users, 100) // 每次批量插入100条记录
索引 合理设计索引可以显著提高查询速度。
db.Model(&User{}).AddIndex("idx_name_email", "name", "email")
避免不必要的数据加载 使用预加载 (Preload) 可以避免 N+1 查询问题。
db.Preload("Posts").First(&user, 1)
正确处理错误可以避免程序崩溃或数据不一致的问题。
result := db.Create(&user)
if result.Error != nil {
log.Fatal(result.Error)
}
遵循一些最佳实践可以提高代码质量和可维护性。
使用结构体标签 使用结构体标签定义数据库字段可以提高代码的可读性和可维护性。
type User struct {
gorm.Model
Name string `gorm:"not null"`
Email string `gorm:"unique;not null"`
}
复杂查询 对于复杂的查询,考虑使用子查询或连接查询。
db.Table("users").
Select("users.*, profiles.address").
Joins("left join profiles on users.id = profiles.user_id").
Where("users.age > ?", 18).
Order("users.created_at desc").
Find(&users)
更新依赖库 定期更新依赖库到最新版本可以获取最新的功能和修复已知的问题。
go get -u gorm.io/gorm
首先,确保你的环境中已经安装了 Go 和一个支持的数据库驱动。然后通过以下命令安装 xorm:
go get -u github.com/go-xorm/xorm
连接数据库
import (
"github.com/go-xorm/xorm"
_ "github.com/go-sql-driver/mysql" // MySQL 驱动
)
func main() {
engine, err := xorm.NewEngine("mysql", "root:password@/test?charset=utf8")
if err != nil {
panic(err)
}
defer engine.Close()
// 显示 SQL 日志
engine.ShowSQL(true)
}
创建模型 定义一个简单的用户模型:
type User struct {
ID int64
Name string
Email string
}
// 表名映射
func (User) TableName() string {
return "users"
}
自动迁移
engine.Sync2(new(User))
创建记录
user := User{Name: "张三", Email: "zhangsan@example.com"}
engine.Insert(&user)
查询记录
var user User
has, err := engine.Id(1).Get(&user)
if err != nil || !has {
fmt.Println("查询失败")
} else {
fmt.Println(user.Name, user.Email)
}
例如,用户和其个人资料的关系:
type Profile struct {
ID int64
UserID int64
Address string
}
type User struct {
ID int64
Name string
Email string
Profile Profile
}
// 表名映射
func (Profile) TableName() string {
return "profiles"
}
func (User) TableName() string {
return "users"
}
创建和读取关联数据:
profile := Profile{Address: "上海市"}
engine.Insert(&profile)
user := User{Name: "张三", Email: "zhangsan@example.com", Profile: profile}
engine.Insert(&user)
var user User
has, err := engine.Id(1).Get(&user)
if err != nil || !has {
fmt.Println("查询失败")
} else {
fmt.Println(user.Name, user.Profile.Address)
}
例如,用户和其文章的关系:
type Post struct {
ID int64
Title string
UserID int64
}
type User struct {
ID int64
Name string
Email string
Posts []Post
}
// 表名映射
func (Post) TableName() string {
return "posts"
}
func (User) TableName() string {
return "users"
}
创建和读取关联数据:
user := User{Name: "张三", Email: "zhangsan@example.com"}
engine.Insert(&user)
post := Post{Title: "我的第一篇文章", UserID: user.ID}
engine.Insert(&post)
var user User
has, err := engine.Id(1).Get(&user)
if err != nil || !has {
fmt.Println("查询失败")
} else {
for _, post := range user.Posts {
fmt.Println(post.Title)
}
}
例如,用户和其关注的用户的关系:
type User struct {
ID int64
Name string
Email string
Follows []User
}
// 表名映射
func (User) TableName() string {
return "users"
}
创建和读取关联数据:
user1 := User{Name: "张三", Email: "zhangsan@example.com"}
user2 := User{Name: "李四", Email: "lisi@example.com"}
engine.Insert(&user1)
engine.Insert(&user2)
engine.Table("users").Exec("INSERT INTO follows (follower_id, following_id) VALUES (?, ?)", user1.ID, user2.ID)
var user User
has, err := engine.Id(1).Get(&user)
if err != nil || !has {
fmt.Println("查询失败")
} else {
for _, follow := range user.Follows {
fmt.Println(follow.Name)
}
}
批量插入和更新数据可以显著提高性能。
批量插入
users := []User{
{Name: "张三", Email: "zhangsan@example.com"},
{Name: "李四", Email: "lisi@example.com"},
{Name: "王五", Email: "wangwu@example.com"},
}
engine.Insert(users)
批量更新
engine.Table("users").Where("age < ?", 30).Update(map[string]interface{}{"age": 30})
事务处理可以确保一系列操作要么全部成功,要么全部失败。
session := engine.NewSession()
defer session.Close()
if err := session.Begin(); err != nil {
panic(err)
}
if _, err := session.Id(1).Get(&user); err != nil {
session.Rollback()
panic(err)
}
if _, err := session.Model(&user).Update(map[string]interface{}{"age": 30}); err != nil {
session.Rollback()
panic(err)
}
if err := session.Commit(); err != nil {
panic(err)
}
性能优化对于大型应用至关重要。
批处理 批量插入和批量更新可以减少数据库的网络开销。
engine.InsertInBatches(users, 100) // 每次批量插入100条记录
索引 合理设计索引可以显著提高查询速度。
engine.Exec("ALTER TABLE users ADD INDEX idx_name_email (name, email)")
避免不必要的数据加载 使用预加载可以避免 N+1 查询问题。
var user User
has, err := engine.Id(1).Join("INNER", "profiles", "users.id = profiles.user_id").Get(&user)
if err != nil || !has {
fmt.Println("查询失败")
} else {
fmt.Println(user.Name, user.Profile.Address)
}
正确处理错误可以避免程序崩溃或数据不一致的问题。
result, err := engine.Id(1).Get(&user)
if err != nil {
log.Fatal(err)
} else if !result {
fmt.Println("未找到记录")
}
遵循一些最佳实践可以提高代码质量和可维护性。
使用结构体标签 使用结构体标签定义数据库字段可以提高代码的可读性和可维护性。
type User struct {
ID int64 `xorm:"pk autoincr"`
Name string `xorm:"not null"`
Email string `xorm:"unique not null"`
}
func (User) TableName() string {
return "users"
}
复杂查询 对于复杂的查询,考虑使用子查询或连接查询。
var users []User
engine.Table("users").
Select("users.*, profiles.address").
Join("LEFT", "profiles", "users.id = profiles.user_id").
Where("users.age > ?", 18).
Desc("users.created_at").
Find(&users)
更新依赖库 定期更新依赖库到最新版本可以获取最新的功能和修复已知的问题。
go get -u github.com/go-xorm/xorm
如果觉得我的文章对您有用,请随意打赏。你的支持将鼓励我继续创作!