目 录CONTENT

文章目录

golang集合gorm对数据库CRUD

懿曲折扇情
2025-10-29 / 0 评论 / 1 点赞 / 14 阅读 / 2,818 字 / 正在检测是否收录...
温馨提示:
本文最后更新于 2025-10-29,若内容或图片失效,请留言反馈。部分素材来自网络,若不小心影响到您的利益,请联系我们删除。
广告 广告

事务语句

package main

/*
题目2:事务语句
假设有两个表: accounts 表(包含字段 id 主键, balance 账户余额)和 transactions 表
(包含字段 id 主键, from_account_id 转出账户ID, to_account_id 转入账户ID, amount 转账金额)。
要求 :
编写一个事务,实现从账户 A 向账户 B 转账 100 元的操作。在事务中,需要先检查账户 A 的余额是否足够,
如果足够则从账户 A 扣除 100 元,向账户 B 增加 100 元,并在 transactions 表中记录该笔转账信息。如果余额不足,则回滚事务。
*/
import (
	"fmt"
	"log"

	"gorm.io/driver/mysql"
	"gorm.io/gorm"
)

type Account struct {
	ID      uint `gorm:"primaryKey"`
	Balance int
}

type Transaction struct {
	ID            uint `gorm:"primaryKey"`
	FromAccountID uint
	ToAccountID   uint
	Amount        int
}

func main() {
	//配置MySQL连接参数
	username := "root"      //账号
	password := "gjs199074" //密码
	host := "127.0.0.1"     //数据库地址,可以是Ip或者域名
	port := 3306            //数据库端口
	Dbname := "web3_test"   //数据库名
	timeout := "10s"        //连接超时,10秒

	//拼接dsn参数,这里使用Sprintf动态拼接
	dsn := fmt.Sprintf("%s:%s@tcp(%s:%d)/%s?charset=utf8&parseTime=True&loc=Local&timeout=%s", username, password, host, port, Dbname, timeout)
	//连接MYSQL, 获得DB类型实例,用于后面的数据库读写操作。
	db, err := gorm.Open(mysql.Open(dsn), &gorm.Config{})
	if err != nil {
		panic("连接数据库失败, error=" + err.Error())
	}
	fmt.Println(db)
	fmt.Println("连接成功")
	// 自动迁移表结构
	db.AutoMigrate(&Account{}, &Transaction{})
	// 初始化账户A余额为500
	db.FirstOrCreate(&Account{ID: 1, Balance: 500})
	db.FirstOrCreate(&Account{ID: 2, Balance: 0})

	// 示例转账
	fromAccountID := uint(1)
	toAccountID := uint(2)
	amount := 100

	if err := TransferMoney(db, fromAccountID, toAccountID, amount); err != nil {
		log.Printf("转账失败: %v", err)
	} else {
		log.Println("转账成功")
	}
}

func TransferMoney(db *gorm.DB, fromID, toID uint, amount int) error {
	tx := db.Begin()
	defer func() {
		if r := recover(); r != nil {
			tx.Rollback()
		}
	}()

	if err := tx.Error; err != nil {
		return err
	}

	// 检查转出账户余额
	var fromAccount Account
	if err := tx.First(&fromAccount, fromID).Error; err != nil {
		tx.Rollback()
		return fmt.Errorf("查询转出账户失败: %w", err)
	}

	if fromAccount.Balance < amount {
		tx.Rollback()
		return fmt.Errorf("账户余额不足")
	}

	// 更新账户余额
	if err := tx.Model(&Account{}).Where("id = ?", fromID).
		Update("balance", gorm.Expr("balance - ?", amount)).Error; err != nil {
		tx.Rollback()
		return fmt.Errorf("扣除转出账户失败: %w", err)
	}

	if err := tx.Model(&Account{}).Where("id = ?", toID).
		Update("balance", gorm.Expr("balance + ?", amount)).Error; err != nil {
		tx.Rollback()
		return fmt.Errorf("增加转入账户失败: %w", err)
	}

	// 记录交易
	transaction := Transaction{
		FromAccountID: fromID,
		ToAccountID:   toID,
		Amount:        amount,
	}
	if err := tx.Create(&transaction).Error; err != nil {
		tx.Rollback()
		return fmt.Errorf("记录交易失败: %w", err)
	}

	return tx.Commit().Error
}

查询语句

package main

/*

题目1:使用SQL扩展库进行查询
假设你已经使用Sqlx连接到一个数据库,并且有一个 employees 表,包含字段 id 、 name 、 department 、 salary 。
要求 :
编写Go代码,使用Sqlx查询 employees 表中所有部门为 "技术部" 的员工信息,并将结果映射到一个自定义的 Employee 结构体切片中。
编写Go代码,使用Sqlx查询 employees 表中工资最高的员工信息,并将结果映射到一个 Employee 结构体中。
*/
import (
	"fmt"

	_ "github.com/go-sql-driver/mysql"
	"gorm.io/driver/mysql"
	"gorm.io/gorm"
)

type Employee struct {
	ID         int
	Name       string
	Department string
	Salary     int
}

func main() {
	//配置MySQL连接参数
	username := "root"      //账号
	password := "gjs199074" //密码
	host := "127.0.0.1"     //数据库地址,可以是Ip或者域名
	port := 3306            //数据库端口
	Dbname := "web3_test"   //数据库名
	timeout := "10s"        //连接超时,10秒

	//拼接dsn参数,这里使用Sprintf动态拼接
	dsn := fmt.Sprintf("%s:%s@tcp(%s:%d)/%s?charset=utf8&parseTime=True&loc=Local&timeout=%s", username, password, host, port, Dbname, timeout)
	//连接MYSQL, 获得DB类型实例,用于后面的数据库读写操作。
	db, err := gorm.Open(mysql.Open(dsn), &gorm.Config{})
	if err != nil {
		panic("连接数据库失败, error=" + err.Error())
	}
	fmt.Println(db)
	fmt.Println("连接成功")

	db.AutoMigrate(&Employee{})
	Employees := []*Employee{
		{ID: 1, Name: "小张", Department: "技术部", Salary: 7000},
		{ID: 2, Name: "小王", Department: "市场部", Salary: 6000},
		{ID: 3, Name: "小李", Department: "技术部", Salary: 8000},
		{ID: 4, Name: "小可", Department: "技术部", Salary: 9000},
	}
	result1 := db.Create(&Employees) //通过数据指针来创建
	println(result1.RowsAffected)
	// 查询技术部员工
	// 查询技术部员工
	var techEmployees []Employee
	result := db.Where("Department = ?", "技术部").Find(&techEmployees)
	if result.Error != nil {
		fmt.Println("查询失败:", result.Error)
		return
	}

	// 打印技术部员工信息
	fmt.Println("技术部员工信息:")
	for _, emp := range techEmployees {
		fmt.Printf("ID: %d, Name: %s, Department: %s, Salary: %d\n", emp.ID, emp.Name, emp.Department, emp.Salary)
	}

	// 并将结果映射到一个自定义的 Employee 结构体切片中
	// 查询工资最高的员工
	var highestPaidEmployee Employee
	result2 := db.Order("Salary DESC").First(&highestPaidEmployee)
	if result2.Error != nil {
		fmt.Println("查询失败:", result2.Error)
		return
	}

	// 打印工资最高的员工信息
	fmt.Println("工资最高的员工信息:")
	fmt.Printf("ID: %d, Name: %s, Department: %s, Salary: %d\n", highestPaidEmployee.ID, highestPaidEmployee.Name, highestPaidEmployee.Department, highestPaidEmployee.Salary)
}

基本CRUD

/*
目1:基本CRUD操作
假设有一个名为 students 的表,包含字段 id (主键,自增)、 name (学生姓名,字符串类型)、 age (学生年龄,整数类型)、 grade (学生年级,字符串类型)。
要求 :
编写SQL语句向 students 表中插入一条新记录,学生姓名为 "张三",年龄为 20,年级为 "三年级"。
编写SQL语句查询 students 表中所有年龄大于 18 岁的学生信息。
编写SQL语句将 students 表中姓名为 "张三" 的学生年级更新为 "四年级"。
编写SQL语句删除 students 表中年龄小于 15 岁的学生记录。
*/

// -- 插入新记录
// INSERT INTO students (name, age, grade) VALUES ('张三', 20, '三年级');

// -- 查询年龄大于18岁的学生
// SELECT * FROM students WHERE age > 18;

// -- 更新张三的年级
// UPDATE students SET grade = '四年级' WHERE name = '张三';

// -- 删除年龄小于15岁的学生

// DELETE FROM students WHERE age < 15;

// 使用golang去执行上述SQL语句
package main

import (
	"fmt"

	"gorm.io/driver/mysql"
	"gorm.io/gorm"
)

type Student struct {
	gorm.Model
	ID    int
	Name  string
	Age   int
	Grade string
}

func main() {
	//配置MySQL连接参数
	username := "root"      //账号
	password := "gjs199074" //密码
	host := "127.0.0.1"     //数据库地址,可以是Ip或者域名
	port := 3306            //数据库端口
	Dbname := "web3_test"   //数据库名
	timeout := "10s"        //连接超时,10秒

	//拼接dsn参数,这里使用Sprintf动态拼接
	dsn := fmt.Sprintf("%s:%s@tcp(%s:%d)/%s?charset=utf8&parseTime=True&loc=Local&timeout=%s", username, password, host, port, Dbname, timeout)
	//连接MYSQL, 获得DB类型实例,用于后面的数据库读写操作。
	db, err := gorm.Open(mysql.Open(dsn), &gorm.Config{})
	if err != nil {
		panic("连接数据库失败, error=" + err.Error())
		fmt.Println(db)
		fmt.Println("连接成功")

	}
	db.AutoMigrate(&Student{})
	students := []*Student{
		{ID: 1, Name: "张三", Age: 20, Grade: "三年级"},
		{ID: 2, Name: "小王", Age: 34, Grade: "八年级"},
		{ID: 3, Name: "小李", Age: 12, Grade: "九年级"},
		{ID: 4, Name: "小可", Age: 21, Grade: "六年级"},
	}
	result1 := db.Debug().Create(&students) //通过数据指针来创建
	println(result1.RowsAffected)

	//查询数据
	result2 := db.Debug().Where("age > ?", 18).Find(&students)
	println(result2.RowsAffected)
	//更新数据
	result3 := db.Debug().Model(&Student{}).Where("name = ?", "张三").Update("grade", "四年级")
	println(result3.RowsAffected)
	//删除数据
	result4 := db.Debug().Where("age < ?", 15).Delete(&Student{})
	println(result4.RowsAffected)
}

GORM 模型定义

package main

/*
题目1:模型定义
假设你要开发一个博客系统,有以下几个实体: User (用户)、 Article (文章)、 Comment (评论)。
要求 :
使用Gorm定义 User 、 Article 和 Comment 模型,其中 User 与 Article 是一对多关系(一个用户可以发布多篇文章),
Article 与 Comment 也是一对多关系(一篇文章可以有多个评论)。
编写Go代码,使用Gorm创建这些模型对应的数据库表。

*/

import (
	"fmt"
	"log"

	"gorm.io/driver/mysql"
	"gorm.io/gorm"
)

type User struct {
	gorm.Model
	Username string    `gorm:"unique;not null"`
	Email    string    `gorm:"type:varchar(255);not null"`
	Password string    `gorm:"not null"`
	Articles []Article `gorm:"foreignKey:UserID"`
}

type Article struct {
	gorm.Model
	Title    string    `gorm:"not null"`
	Content  string    `gorm:"type:text"`
	UserID   uint      `gorm:"not null"`
	Comments []Comment `gorm:"foreignKey:ArticleID"`
}

type Comment struct {
	gorm.Model
	Content   string `gorm:"type:text"`
	ArticleID uint   `gorm:"not null"`
	UserID    uint   `gorm:"not null"`
}

func main() {
	//配置MySQL连接参数
	username := "root"      //账号
	password := "gjs199074" //密码
	host := "127.0.0.1"     //数据库地址,可以是Ip或者域名
	port := 3306            //数据库端口
	Dbname := "web3_test"   //数据库名
	timeout := "10s"        //连接超时,10秒

	//拼接dsn参数,这里使用Sprintf动态拼接
	dsn := fmt.Sprintf("%s:%s@tcp(%s:%d)/%s?charset=utf8&parseTime=True&loc=Local&timeout=%s", username, password, host, port, Dbname, timeout)
	//连接MYSQL, 获得DB类型实例,用于后面的数据库读写操作。
	db, err := gorm.Open(mysql.Open(dsn), &gorm.Config{})
	if err != nil {
		panic("连接数据库失败, error=" + err.Error())
	}
	fmt.Println(db)
	fmt.Println("连接成功")

	// 自动迁移模型
	err = db.AutoMigrate(&User{}, &Article{}, &Comment{})
	if err != nil {
		log.Fatal("Failed to migrate tables:", err)
	}

	fmt.Println("Database tables created successfully!")

	//创建用户、文章、评论
	var users = []User{
		{Username: "科比", Email: "112345678@QQ.COM", Password: "123456", Articles: []Article{
			{Title: "GORM教程", Content: "这是关于GORM的教程文章", UserID: 1, Comments: []Comment{
				{Content: "很有帮助的文章!", UserID: 1, ArticleID: 1}}}}},
		{Username: "乔丹", Email: "112345678@QQ.COM", Password: "123456", Articles: []Article{
			{Title: "GORM高级用法", Content: "这是关于GORM的高级用法文章", UserID: 2, Comments: []Comment{
				{Content: "学到了很多新知识!", UserID: 2, ArticleID: 2}, {Content: "太强了学到好多知识,给你点赞!", UserID: 2, ArticleID: 2}}}}}}

	result1 := db.Create(users) //通过数据切片来创建
	println(result1.RowsAffected)
	// 查询某个用户发布的所有文章及其对应的评论信息
	var user User
	userID := 1 // 假设要查询的用户 ID 为 1
	err = db.Preload("Articles.Comments").First(&user, userID).Error
	if err != nil {
		fmt.Println("查询失败:", err)
		return
	}

	// 打印结果
	fmt.Printf("用户: %s\n", user.Username)
	for _, article := range user.Articles {
		fmt.Printf("文章: %s\n", article.Title)
		for _, comment := range article.Comments {
			fmt.Printf("评论: %s\n", comment.Content)
		}
	}

	// 查询评论数量最多的文章信息
	var article Article
	err = db.Model(&Article{}).
		Select("articles.*, COUNT(comments.id) as comment_count ").
		Joins("left join comments on comments.article_id = articles.id").
		Group("articles.id").
		Order("comment_count DESC").
		Limit(1).
		Find(&article).Error
	if err != nil {
		fmt.Println("查询失败:", err)
		return
	}

	// 打印结果
	fmt.Printf("评论数量最多的文章: %s\n", article.Title)

}
1

评论区