首页 > 数据库 >gorm数据库操作

gorm数据库操作

时间:2023-04-14 22:14:42浏览次数:61  
标签:数据库 fmt db user Println 操作 gorm User

前言:

Object-Relationl Mapping,它的作用是在关系型数据库和对象之间作一个映射,这样,我们在具体的操作数据库的时候,就不需要再去和复杂的SQL语句打交道,只要像平时操作对象一样操作它就可以了 。

GORM是golang写的ORM库

网址:https://gorm.io/

正文:

GORM 官方支持的数据库类型有: MySQL, PostgreSQL, SQlite, SQL Server

安装gorm:

go get -u  gorm.io/gorm

go get -u gorm.io/driver/mysql    //mysql 驱动

 

链接mysql实例:

var db *gorm.DB
var dbErr error

func init() {
    dsn := "root:root123456@tcp(127.0.0.1:3306)/yangtest?charset=utf8"
    db, dbErr = gorm.Open(mysql.Open(dsn))
    if dbErr != nil {
        log.Fatal(dbErr.Error())
    }
    fmt.Println("mysql 连接成功")
}

 

模型定义自动迁移tag标签

根据标签自动生成表示例:

type User struct {
    //gorm.Model
    Id       int    `gorm:"type:int;primary key"`
    Name     string `gorm:"type:varchar(20);not null;index"`
    Email    string `gorm:"type:varchar(20)"`
    Age      int    `gorm:"type:tinyint(20);unsigned"`
    CreateAt int64  `gorm:"type:int(20);unsigned;not null;autoCreateTime"`
    UpdateAt int64  `gorm:"type:int(20);unsigned;not null;autoUpdateTime;default:0"`
}


var db *gorm.DB
var dbErr error

func init() {
    dsn := "root:root123456@tcp(127.0.0.1:3306)/yangtest?charset=utf8"
    db, dbErr = gorm.Open(mysql.Open(dsn))
    if dbErr != nil {
        log.Fatal(dbErr.Error())
    }
    fmt.Println("mysql 连接成功")
}

func main() {
    db.Set("gorm:table_options", "ENGINE=InnoDB").AutoMigrate(&User{})
}

运行程序,即可看到数据库生成了 users表,表结构如下:

 

CREATE TABLE `users` (
  `id` bigint(20) NOT NULL AUTO_INCREMENT,
  `name` varchar(20) NOT NULL,
  `email` varchar(20) DEFAULT NULL,
  `age` tinyint(20) DEFAULT NULL,
  `create_at` int(20) NOT NULL,
  `update_at` int(20) NOT NULL DEFAULT '0',
  PRIMARY KEY (`id`),
  KEY `idx_users_name` (`name`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

 

 

 

tag标记列表:

 

 

 

配置表名:

默认生成的表名是 是结构体名称的复数形式,如果自定义其他表名,

就需要使用  TableName方法进行配置表名

 

//根据结构体自定义表名
func (u *User) TableName() string {
    return "user"
}

 

全局配置表前缀及表名:

如果需要全局表名不加复数,以及全局增加表前缀,就在连接数据库的时候进行全局配置

 

func init() {
    dsn := "root:root123456@tcp(127.0.0.1:3306)/yangtest?charset=utf8"
    db, dbErr = gorm.Open(mysql.Open(dsn), &gorm.Config{
        //全局配置
        NamingStrategy: schema.NamingStrategy{
            SingularTable: true,    //表名不增加复数
            TablePrefix:   "shop_", //增加表前缀
        },
    })
    if dbErr != nil {
        log.Fatal(dbErr.Error())
    }
}

 

 

gorm操作数据库增删改查

插入数据:

func InsertData()  {
    user := User{Name: "lampol44", Age: 23, Email: "[email protected]"}
    //res := db.Create(&user)
    //fmt.Println(res.RowsAffected, res.Error, user.Id) //输出1 <nil> 1

    //插入字段插入
    //res := db.Select("name", "age").Create(&user)
    //fmt.Println(res.RowsAffected, res.Error, user.Id)

    //排除某字段插入
    res := db.Omit("email").Create(&user)
    fmt.Println(res.RowsAffected, res.Error, user.Id)
}

 

批量插入数据:

func InsertDataMul()  {

//定义一个结构体数组
    user := []User{
        {Name: "lampol3", Age: 23, Email: "[email protected]"},
        {Name: "lampol4", Age: 24, Email: "[email protected]"},
        {Name: "lampol5", Age: 25, Email: "[email protected]"},
        {Name: "lampol6", Age: 26, Email: "[email protected]"},
    }
    res := db.Create(&user)
    fmt.Println(res.RowsAffected, res.Error)
}

使用map单条插入数据:

使用map的话,因为没有标签,不会自动生成 create_at 字段,也无法获取到插入的id

所以不建议使用map作为插入数据的参数

 

func InsertData()  {
    var user map[string]interface{}
    user = make(map[string]interface{})

    user["name"] = "lampol8"
    user["age"] = 55
    user["email"] = "[email protected]"
    user["create_at"] = time.Now().Unix()

    //res := db.Model(&User{}).Create(&user)
    res := db.Table("users").Create(&user)

    fmt.Println(user)
    fmt.Println(res.RowsAffected, res.Error)
}

 

 

 

如果不写入 create_at 会报错

 

 

 

查询数据

First,Last,Take

使用结构体接收数据:

var user User
    //获取第一条数据
    db.First(&user)
    fmt.Println(user)

    //获取第一条数据
    db.Take(&user)
    fmt.Println(user)

    //获取最后一条数据
    db.Last(&user)
    fmt.Println(user)

使用map接收数据:

var data = map[string]interface{}{}
    db.Model(&User{}).First(&data)
    fmt.Println(data)

    db.Model(&User{}).Take(&data)
    fmt.Println(data)

    db.Model(&User{}).Last(&data)
    fmt.Println(data)
    
    fmt.Println(data["id"])

 

 

使用take获取ID为6的数据

    var user User
    db.Take(&user, 6)
    fmt.Println(user)

 

使用take获取name为lampol6的数据

    //查询 name 为 lampol5的记录
    var user User
    db.Take(&user, "name", "lampol6")
    fmt.Println(user)

查询多条数据

使用find查询全部数据

var users []User
    db.Find(&users)
    fmt.Println(users)

使用find查询多条ID的数据

    var users []User
    db.Find(&users, []int{3, 4, 5, 6, 7})
    fmt.Println(users)

使用scan查询多条数据

    var users []User
    db.Model(&User{}).Scan(&users)
    fmt.Println(users)

 

使用find根据条件查询多条

var users []User
    //一个条件
    db.Find(&users, "age=?", 26)
    fmt.Println(users)
    //多个条件
    db.Find(&users, User{
        Name: "lampol6",
        Age:  26,
    })
    fmt.Println(users)

使用where查询多条

var users []User
    //单个where查询
    db.Where("age=?", 26).Find(&users)
    fmt.Println(users)
    //多个where查询
    db.Where("age=?", 26).Where("name=?", "lampol6").Find(&users)
    fmt.Println(users)

    //不等于查询
    db.Where("age<>?", 26).Find(&users)
    fmt.Println(users)
    //in查询
    db.Where("name in ?", []string{"lampol4", "lampol5"}).Find(&users)
    fmt.Println(users)

    //select查询指定字段
    db.Select([]string{"name", "age"}).Where("name in ?", []string{"lampol4", "lampol5"}).Find(&users)
    fmt.Println(users)

    //排序 order 和 limit
    db.Where("age=?", 26).Order("id DESC").Limit(2).Find(&users)
    fmt.Println(users)

多表,连表查询:

type OrderList struct {
        Name      string
        GoodsName string
    }

    var userOrder []OrderList

    db.Table("shop_user").Select("shop_user.name", "shop_order_list.goods_name").
        Joins("join shop_order_list on shop_user.id=shop_order_list.user_id").Find(&userOrder)
    fmt.Println(userOrder)

查询数量:

var count int64
    //db.Model(&User{}).Where("age=?", 26).Count(&count)
    db.Table("shop_user").Where("age=?", 26).Count(&count)
    fmt.Println(count)

 

更新数据:

//更新数据
    res := db.Model(&User{}).Where("id=?", 5).Update("age", 45)
    fmt.Println(res.RowsAffected)

    //更新多个字段
    res := db.Model(&User{}).Where("id=?", 6).Updates(&User{Name: "yangphp", Age: 32})
    fmt.Println(res.RowsAffected)

//查询出来,然后使用save更新
    var user User
    db.First(&user)
    user.Age = 44
    user.Name = "lampol_88"
    db.Save(&user)

//原生sql更新
db.Exec("UPDATE shop_user SET name=?", "lampol")

//删除
//db.Delete(&User{}, 5)       //删除一条
db.Delete(&User{}, []int{6, 7}) //删除多条

原生sql增删查改:

//插入数据
    db.Exec("INSERT INTO shop_user (name,age,email,is_sex) VALUES(?,?,?,?)", "lampol_4", 55, "[email protected]", 1)
    //更新
    res := db.Exec("UPDATE shop_user SET name=? WHERE id=?", "lampol_2", 5)
    //更新, expr做计算
    db.Exec("UPDATE shop_user SET age=? WHERE id=?", gorm.Expr("age+?", 5), 5)
    //删除
    res := db.Exec("DELETE FROM shop_user  WHERE id=?", 7)

//查询数据:
type Result struct {
        Name string
        Age  int
    }
    var result []Result
    db.Raw("SELECT name,age FROM shop_user WHERE id=? ", 8).Scan(&result)
    db.Raw("SELECT name,age FROM shop_user WHERE id IN ? ", []int{5, 6, 8}).Scan(&result)

    var age int  //查询单个字段
    db.Raw("SELECT age FROM shop_user WHERE id=? ", 6).Scan(&age)
    fmt.Println(result)

 

GORM  DryRun模式

生成 SQL 但不执行。 它可以用于准备或测试生成的 SQL

 

dsn := “root:123456@tcp(127.0.0.1:3306)/shop?charset=utf8mb4&parseTime=True&loc=Local”
db, err = gorm.Open(mysql.Open(dsn), &gorm.Config{
   NamingStrategy: schema.NamingStrategy{
      Table: true,
      TablePrefix:   “shop_”,
   },
   DryRun: true, //全局打开  sql语句不会执行
})

user := User{Name: "lampol", Age: 23, Email: "[email protected]", Sex: 1}
stmt := db.Create(&user).Statement
fmt.Println(db.Dialector.Explain(stmt.SQL.String(), stmt.Vars...))

 

 

 

不在全局生效的DryRun模式:

var user User
res := db.Session(&gorm.Session{DryRun: true}).First(&user).Statement.SQL.String()
fmt.Println(res)

 

gorm钩子

Hook 是在创建、查询、更新、删除等操作之前、之后调用的函数

钩子方法的函数签名应该是 func(*gorm.DB) error

插入   BeforeSave   BeforeCreate    AfterCreate     AfterSave

更新    BeforeSave    BeforeUpdate   AfterUpdate    AfterSave

删除    BeforeDelete     AfterDelete

查询   AfterFind

钩子代码示例1:

 

// 定义钩子
func (u *User) BeforeSave(tx *gorm.DB) (err error) {
    fmt.Println("BeforeSave....")
    return
}
func (u *User) BeforeCreate(tx *gorm.DB) (err error) {
    fmt.Println("BeforeCreate....")
    return
}
func (u *User) AfterSave(tx *gorm.DB) (err error) {
    fmt.Println("AfterSave....")
    return
}
func (u *User) AfterCreate(tx *gorm.DB) (err error) {
    fmt.Println("AfterCreate....")
    return
}


func main() {
    user := User{Name: "lampol33", Age: 33, Email: "[email protected]"}
    db.Create(&user)
    fmt.Println("create ....")

    //更新
    db.Model(&User{}).Where("id=?", 11).Update("name", "lampol_9")
    fmt.Println("update ....")

    //使用 table,未使用Model,无法使用钩子
    //db.Table("shop_user").Where("id=?", 11).Update("name", "lampol_9")}

 

打印结果:

 

 

 

GORM  事务

数据表引擎需要 innodb类型才可以使用事务

show create table  shop_user;

alter table shop_user  engine="innodb";

// 开始事务
tx := db.Begin()
// 遇到错误时回滚事务
tx.Rollback()
// 提交事务
tx.Commit()

事务示例1:

 

tx := db.Begin()
    user := User{Name: "lampol44", Age: 44, Email: "[email protected]"}
    delnum := tx.Delete(&User{}, 100).RowsAffected

    insNum := tx.Create(&user).RowsAffected
    fmt.Println(delnum, insNum)

    if delnum != 1 || insNum != 1 {
        //失败 回滚
        fmt.Println("rollback ....")
        tx.Rollback()
        return
    }
//未失败,提交
    tx.Commit()
    fmt.Println("commit ....")

 

 

 

完结

 

标签:数据库,fmt,db,user,Println,操作,gorm,User
From: https://www.cnblogs.com/ypeih/p/17320080.html

相关文章

  • python分段读取word文件数据到MySQL数据库和Java读取word数据到MySQL数据库
    1、python分段读取word文件数据到MySQL数据库示例:(注:此示例为读取某个文件夹下的所有文件,并对文件后缀名为doc的文件进行读取,并以文件名称为id完成对该word内容的插入。)#导入os模块importos#导入所需库importpymysqlfromdocximportDocument#path定义要获取的......
  • kafka的基本操作
    1、配置启动文件//首先cd到kafka的config目录vimserver.properties//找到listeners配置项,如果注释掉了,就删除注释listeners=PLAINTEXT://127.0.0.1.9092//修改日志文件的位置,这个文件夹需要你自己创建log.dirs=/usr/local/kafka/kafka-logs//修改连接zookeepe......
  • docker03 容器操作 应用部署 迁移备份 dockerfile
    今日内容详细目录今日内容详细1容器操作2应用部署2.1mysql部署2.2redis部署2.3nginx部署3迁移与备份4Dockerfile1容器操作#启动容器 dockerstart容器id#停止容器 dockerstop容器id#文件拷贝 #容器的文件copy到宿主机上(不是在容器内执行)dockercp容......
  • 运行mysql容器以及通过命令行访问数据库
    运行mysql容器下面命令将创建一个名为mysql-8.0.31的容器,并将容器中的MySQL根密码设置为root。dockerrun--namemysql-8.0.31-p3306:3306-eMYSQL_ROOT_PASSWORD=root-dmysql:8.0.31访问mysqlmysql-h127.0.0.1-P3306-u<username>-p导入sql文件创建数据......
  • Java接收到MySQL数据库查询出的date类型的数据输出格式不对
    问题查询某条数据,里面有个effective_time字段,数据库里保存的该条数据的effective_time的值是2023-04-13,但是使用postman调用接口,返回的确是2023-04-12T16:00:00.000+00:00,不仅格式不对,而且时间还慢了一天。但是在application.yml中配置数据库连接的时候,确实指定了时区......
  • 解决帆软Report连接数据库是出现未下载驱动问题
    1.在帆软Report连接数据库的时候一直出现问题,还有就是版本11的不太好用,建议使用版本10的下载驱动在官网都是英文看不懂,直接在csdn上搜即可,然后需要把下载下来的驱动放在这个目录下,这样帆软连接数据库的问题解决 ......
  • MySQL数据库实现主主同步
    前言MySQL主主同步实际上是在主从同步的基础上将从数据库也提升成主数据库,让它们可以互相读写数据库,从数据库变成主数据库;主从相互授权连接,读取对方binlog日志并更新到本地数据库的过程,只要对方数据改变,自己就跟着改变。1.主主同步的优与劣事实上每个技术都有它的优劣势,我们......
  • 经典案例 | 将扫码枪连接至PROFINET系统(内附详细完整教程 包括操作及参数配置)
     PROFINET网关与SICK扫描枪通讯例程  北京鼎实创新科技股份有限公司目录第一章系统目的及连接.............................................................................................11.1系统目的...........................................................
  • 批量给mycat配置文件增加数据库节点
    #!/bin/bash#修改mysqlschemamycat_schema_file=/opt/mycat/conf/schema.xmlcp$mycat_schema_file${mycat_schema_file}.bakdatabase_list='messagexuejie'#找到usercenter的行号,由于schema成对出现有可能换行,在其上一行增加schema更可靠last_schema_row_number=`sed......
  • android 读取本地数据库db文件(Android sqlite)
    本文由简悦SimpRead转码,原文地址cloud.tencent.com腾讯云备案控制台开发者社区学习实践活动专区工具TVP文章/答案/技术大牛搜索搜索关闭写文章提问登录/注册全栈程序员站长55.1K篇文章android读取本地数据库db文件(Androidsqlite)转到我的清单专栏首页全栈程序员必看......