【GoWeb框架初探————XORM篇】

1. XORM

xorm 是一个简单而强大的Go语言ORM库. 通过它可以使数据库操作非常简便。
在这里插入图片描述

1.1 特性

  • 支持 Struct 和数据库表之间的灵活映射,并支持自动同步
  • 事务支持
  • 同时支持原始SQL语句和ORM操作的混合执行
  • 使用连写来简化调用
  • 支持使用ID, In, Where, Limit, Join, Having, Table, SQL, Cols等函数和结构体等方式作为条件
  • 支持级联加载Struct
  • Schema支持(仅Postgres)
  • 支持缓存
  • 通过 xorm.io/reverse 支持根据数据库自动生成 xorm 结构体
  • 支持记录版本(即乐观锁)
  • 通过 xorm.io/builder 内置 SQL Builder 支持
  • 上下文缓存支持
  • 支持日志上下文

1.2 驱动支持

目前支持的Go数据库驱动和对应的数据库如下:

  • Mysql5.* / Mysql8.* / Mariadb / Tidb
  • Postgres / Cockroach
  • SQLite
  • MsSql
  • Oracle

1.3 安装

go get xorm.io/xorm

2. 特性功能

2.1 Struct和数据库表映射

func main() {
	// 数据库连接基本信息
	var (
		userName  string = "root"
		password  string = "password"
		ipAddress string = "127.0.0.1"
		port      int    = 3306
		dbName    string = "go_test"
		charset   string = "utf8mb4"
	)
	// 构建数据库连接信息
	conn := fmt.Sprintf("%s:%s@tcp(%s:%d)/%s?charset=%s", userName, password, ipAddress, port, dbName, charset)

	engine, err := xorm.NewEngine("mysql", conn)
	if err != nil {
		fmt.Println("数据库连接失败", err)
	}

	type User struct {
		Id      int64
		Name    string
		Salt    string
		Age     int
		Passwd  string    `xorm:"varchar(200)"`
		Created time.Time `xorm:"created"`
		Updated time.Time `xorm:"updated"`
	}
	// 表同步,以后修改User的结构后只需再执行一遍即可
	err = engine.Sync(new(User))
	if err != nil {
		fmt.Println("表结构同步失败", err)
	}
}

2.2 数据库的基本操作

2.3.1 数据插入

在数据插入的时候,我们应该要使用地址类型,这样方便数据库进行一些回写操作。

user := pojo.User{
		Id:     123456,
		Name:   "gzh",
		Age:    23,
		Passwd: "123456",
	}
// 插入一个对象
// INSERT INTO struct () values ()
n, err := engine.Insert(&user)
// 一次性插入多个
// INSERT INTO struct1 () values ()
// INSERT INTO struct2 () values ()
n, err := engine.Insert(&user1,&user2)
// 插入一个切片
// INSERT INTO struct () values (),(),()
var users []User
users = append(users,user1)
users = append(users,user2)
n, err := engine.Insert(&users)
// 通过map插入数据
// INSERT INTO user (name, age) values (?,?)
affected, err := engine.Table("user").Insert(map[string]interface{}{
    "name": "lunny",
    "age": 18,
})
// 插入列表map数据
// INSERT INTO user (name, age) values (?,?),(?,?)
affected, err := engine.Table("user").Insert([]map[string]interface{}{
    {
        "name": "lunny",
        "age": 18,
    },
    {
        "name": "lunny2",
        "age": 19,
    },
})

2.3.2 数据查找

2.3.2.1 Get查询单条记录
has, err := engine.Get(&user)
// SELECT * FROM user LIMIT 1

has, err := engine.Where("name = ?", name).Desc("id").Get(&user)
// SELECT * FROM user WHERE name = ? ORDER BY id DESC LIMIT 1

// 查询一部分/全部属性
var name string
has, err := engine.Table(&user).Where("id = ?", id).Cols("name").Get(&name)
// SELECT name FROM user WHERE id = ?

var id int64
has, err := engine.Table(&user).Where("name = ?", name).Cols("id").Get(&id)
has, err := engine.SQL("select id from user").Get(&id)
// SELECT id FROM user WHERE name = ?

var id int64
var name string
has, err := engine.Table(&user).Cols("id", "name").Get(&id, &name)
// SELECT id, name FROM user LIMIT 1

var valuesMap = make(map[string]string)
has, err := engine.Table(&user).Where("id = ?", id).Get(&valuesMap)
// SELECT * FROM user WHERE id = ?

var valuesSlice = make([]interface{}, len(cols))
has, err := engine.Table(&user).Where("id = ?", id).Cols(cols...).Get(&valuesSlice)
// SELECT col1, col2, col3 FROM user WHERE id = ?
2.3.2.2 检测记录是否存在
// 检验数据表中是否存在数据
has, err := testEngine.Exist(new(RecordExist))
// SELECT * FROM record_exist LIMIT 1

// 检查数据表中是否存在满足指定条件的数据
has, err = testEngine.Exist(&RecordExist{
		Name: "test1",
	})
// SELECT * FROM record_exist WHERE name = ? LIMIT 1

has, err = testEngine.Where("name = ?", "test1").Exist(&RecordExist{})
// SELECT * FROM record_exist WHERE name = ? LIMIT 1

has, err = testEngine.SQL("select * from record_exist where name = ?", "test1").Exist()
// select * from record_exist where name = ?

has, err = testEngine.Table("record_exist").Exist()
// SELECT * FROM record_exist LIMIT 1

has, err = testEngine.Table("record_exist").Where("name = ?", "test1").Exist()
// SELECT * FROM record_exist WHERE name = ? LIMIT 1
2.3.2.3 Find 查询多条记录
var users []User
err := engine.Where("name = ?", name).And("age > 10").Limit(10, 0).Find(&users)
// SELECT * FROM user WHERE name = ? AND age > 10 limit 10 offset 0

type Detail struct {
    Id int64
    UserId int64 `xorm:"index"`
}

type UserDetail struct {
    User `xorm:"extends"`
    Detail `xorm:"extends"`
}

var users []UserDetail
err := engine.Table("user").Select("user.*, detail.*").
    Join("INNER", "detail", "detail.user_id = user.id").
    Where("user.name = ?", name).Limit(10, 0).
    Find(&users)
// SELECT user.*, detail.* FROM user INNER JOIN detail WHERE user.name = ? limit 10 offset 0
2.3.2.4 Iterate 和 Rows 根据条件遍历数据库
Iterate
err := engine.Iterate(&User{Name:name}, func(idx int, bean interface{}) error {
    user := bean.(*User)
    return nil
})
// SELECT * FROM user

err := engine.BufferSize(100).Iterate(&User{Name:name}, func(idx int, bean interface{}) error {
    user := bean.(*User)
    return nil
})
// SELECT * FROM user Limit 0, 100
// SELECT * FROM user Limit 101, 100
Rows
rows, err := engine.Rows(&User{Name:name})
// SELECT * FROM user
defer rows.Close()
bean := new(Struct)
for rows.Next() {
    err = rows.Scan(bean)
}
//===============或者==================
rows, err := engine.Cols("name", "age").Rows(&User{Name:name})
// SELECT * FROM user
defer rows.Close()
for rows.Next() {
    var name string
    var age int
    err = rows.Scan(&name, &age)
}

2.3.3 数据更新

Update 更新数据,除非使用Cols,AllCols函数指明,默认只更新非空和非0的字段

affected, err := engine.ID(1).Update(&user)
// UPDATE user SET ... Where id = ?

affected, err := engine.Update(&user, &User{Name:name})
// UPDATE user SET ... Where name = ?

var ids = []int64{1, 2, 3}
affected, err := engine.In(ids).Update(&user)
// UPDATE user SET ... Where id IN (?, ?, ?)

// force update indicated columns by Cols
affected, err := engine.ID(1).Cols("age").Update(&User{Name:name, Age: 12})
// UPDATE user SET age = ?, updated=? Where id = ?

// force NOT update indicated columns by Omit
affected, err := engine.ID(1).Omit("name").Update(&User{Name:name, Age: 12})
// UPDATE user SET age = ?, updated=? Where id = ?

affected, err := engine.ID(1).AllCols().Update(&user)
// UPDATE user SET name=?,age=?,salt=?,passwd=?,updated=? Where id = ?

2.3.4 数据删除

Delete 删除记录,需要注意,删除必须至少有一个条件,否则会报错。要清空数据库可以用EmptyTable

affected, err := engine.Where(...).Delete(&user)
// DELETE FROM user Where ...

affected, err := engine.ID(2).Delete(&user)
// DELETE FROM user Where id = ?

affected, err := engine.Table("user").Where(...).Delete()
// DELETE FROM user WHERE ...

2.3.5 其他

2.3.5.1 Count 获取记录条数
counts, err := engine.Count(&user)
// SELECT count(*) AS total FROM user
2.3.5.2 Sum 求和函数
agesFloat64, err := engine.Sum(&user, "age")
// SELECT sum(age) AS total FROM user

agesInt64, err := engine.SumInt(&user, "age")
// SELECT sum(age) AS total FROM user

sumFloat64Slice, err := engine.Sums(&user, "age", "score")
// SELECT sum(age), sum(score) FROM user

sumInt64Slice, err := engine.SumsInt(&user, "age", "score")
// SELECT sum(age), sum(score) FROM user

2.3.5.3 条件编辑器
err := engine.Where(builder.NotIn("a", 1, 2).And(builder.In("b", "c", "d", "e"))).Find(&users)
// SELECT id, name ... FROM user WHERE a NOT IN (?, ?) AND b IN (?, ?, ?)

2.3 事务支持

2.3.1 事务的使用

使用事务可以使得多个sql语句具有原子性。

session := engine.NewSession()
defer session.Close()

// 开启事务
if err := session.Begin(); err != nil {
    // if returned then will rollback automatically
    // 如果发生错误会自动回滚
    return err
}

user1 := Userinfo{Username: "xiaoxiao", Departname: "dev", Alias: "lunny", Created: time.Now()}
if _, err := session.Insert(&user1); err != nil {
    return err
}

user2 := Userinfo{Username: "yyy"}
if _, err := session.Where("id = ?", 2).Update(&user2); err != nil {
    return err
}

if _, err := session.Exec("delete from userinfo where username = ?", user2.Username); err != nil {
    return err
}

// 提交事务
return session.Commit()

2.3.2 事务的简洁写法

res, err := engine.Transaction(func(session *xorm.Session) (interface{}, error) {
    user1 := Userinfo{Username: "xiaoxiao", Departname: "dev", Alias: "lunny", Created: time.Now()}
    if _, err := session.Insert(&user1); err != nil {
        return nil, err
    }

    user2 := Userinfo{Username: "yyy"}
    if _, err := session.Where("id = ?", 2).Update(&user2); err != nil {
        return nil, err
    }

    if _, err := session.Exec("delete from userinfo where username = ?", user2.Username); err != nil {
        return nil, err
    }
    return nil, nil
})

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/562372.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

java学习笔记2

3 选择结构 3.1 if选择结构 3.1.1 基本if结构 语法if(条件){// 代码块 }执行流程 当if条件为真,执行代码块,否则不执行代码块。 代码 public class Demo1 {public static void main(String[] args) {// 需求: 张浩的考试成绩>90分,奖励一部Iphone6sScanner sc = new S…

mapreduce中的ReduceTask工作机制(Hadoop)

ReduceTask 是 Hadoop 中的一个重要组件,负责对 MapTask 的输出进行合并、排序和归并,最终生成最终的输出结果。 ReduceTask 的工作机制 1. 分组(Shuffle)阶段: 在分组阶段,ReduceTask 会从多个 Mapper …

第二届 Oceanbase 开发者大会 实录

第二届 Oceanbase 开发者大会 实录 今天很有幸参加了Oceanbase 开发者大会,我是真的我一开始还不知道什么是Oceanbase ,直到我开了会才知道。看来真的需要多参加一些这样活动。 会议议程 我们科普一下什么是Oceanbase OceanBase 是阿里巴巴集团推出…

FastChat启动与部署通义千问大模型

FastChat简介 FastChat is an open platform for training, serving, and evaluating large language model based chatbots. FastChat powers Chatbot Arena, serving over 10 million chat requests for 70 LLMs.Chatbot Arena has collected over 500K human votes from sid…

Llama 3 实测效果炸裂,一秒写数百字(附镜像站)

这几天大火的llama 3刚刚在https://askmanyai.cn上线了! 玩了一会儿,这个生成速度是真的亚麻呆住。文案写作和代码生成直接爽到起飞,以往gpt要写一两分钟的千字文,llama 3几秒钟就写完了。而且效果甚至感觉更好? 效果惊…

日期相关的题目

日期相关的题目 1. 计算日期到天数转换2. 日期累加3. 打印日期4. 日期差值 1. 计算日期到天数转换 输出示例: 思路&#xff1a;计算前n-1个月的天数在加上这个月的天数。 #include <iostream> using namespace std;int main() {int year, month, day;cin >> yea…

数据结构练习-数据结构概述

----------------------------------------------------------------------------------------------------------------------------- 1. 在数据结构中&#xff0c;从逻辑上可以把数据结构分成( )。 A. 动态结构和静态结构 B. 紧凑结构和非紧凑结构 C. 线性结…

Spring AI Summary

版权声明 本文原创作者&#xff1a;谷哥的小弟作者博客地址&#xff1a;http://blog.csdn.net/lfdfhl Spring AI is a project that aims to streamline the development of AI applications by providing abstractions and reusable components that can be easily integrate…

梯度消失/梯度爆炸

梯度消失/梯度爆炸&#xff08;Vanishing / Exploding gradients&#xff09; 梯度消失或梯度爆炸&#xff1a;训练神经网络的时候&#xff0c;导数或坡度有时会变得非常大&#xff0c;或者非常小&#xff0c;甚至于以指数方式变小&#xff0c;这加大了训练的难度。 g ( z ) …

Java学习Go(入门)

下载Go 《官网下载golang》 直接点Download&#xff0c;然后根据你自己的操作系统进行下载&#xff0c;我这里以win10为例 安装go 默认安装到C:\Program Files\Go&#xff0c;这里我们可以选择安装到其他盘&#xff0c;也可以选择默认安装。初学者建议直接一路next。 安装完…

Java发送邮件 启用SSL

使用的maven依赖: <dependency><groupId>com.sun.mail</groupId><artifactId>javax.mail</artifactId><version>1.4.7</version> </dependency> 配置文件mail.properties如下: # 邮箱配置 email.username=your-email@exa…

(助力国赛)美赛O奖数学建模可视化!!!含代码2(箱型图、旭日图、直方图、三元图、平行坐标图、密度图、局部放大图)

众所周知&#xff0c;数学建模的过程中&#xff0c;将复杂的数据和模型结果通过可视化图形呈现出来&#xff0c;不仅能够帮助我们更深入地理解问题&#xff0c;还能够有效地向评委展示我们的研究成果。   今天&#xff0c;承接《可视化代码1》&#xff0c;作者将与大家分享《…

【软考---系统架构设计师】软件架构

目录 1 一、软件架构的概念 二、软件架构风格 &#xff08;1&#xff09;数据流风格​​​​​​​ &#xff08;2&#xff09;调用/返回风格 &#xff08;3&#xff09;独立构件风格 &#xff08;4&#xff09;虚拟机风格 &#xff08;5&#xff09;仓库风格 三、架构…

【数学建模】优劣解距离法Topsis模型(含MATLAB代码)

TOPSIS法&#xff0c;全称 Technique for Order Preference by Similarity to an Ideal Solution&#xff0c;是由C.L.Hwang和K.Yoon于1981年首次提出的 。这是一种多目标决策分析中常用的有效方法&#xff0c;也被称作优劣解距离法 。 TOPSIS法的基本原理是通过检测评价对象与…

如何使用PHPStudy+Cloudreve搭建个人云盘并实现无公网IP远程访问——“cpolar内网穿透”

文章目录 1、前言2、本地网站搭建2.1 环境使用2.2 支持组件选择2.3 网页安装2.4 测试和使用2.5 问题解决 3、本地网页发布3.1 cpolar云端设置3.2 cpolar本地设置 4、公网访问测试5、结语 1、前言 自云存储概念兴起已经有段时间了&#xff0c;各互联网大厂也纷纷加入战局&#…

uniapp中scroll-view初始化的时候 无法横向滚动到某个为止

项目需求 实现日历&#xff08;13天&#xff09;默认高亮第六天 并定位到第六 左边右边各六天&#xff08;可以滑动&#xff09; 直接上代码 <template><scroll-view class"scroll-X":show-scrollbar"true" :scroll-x"scrollable":…

Chrome 侧边栏开发示例

前言 最近做项目&#xff0c;需要开发浏览器扩展&#xff0c;但是考虑页面布局兼容性问题&#xff0c;使用了Chrome114开始的侧边栏&#xff0c;浏览器自带的能力毕竟不会出现兼容性问题&#xff0c;不过Chrome123开始&#xff0c;侧边栏居然又可以选择固定右侧扩展栏了&#…

C++的初步知识——命名空间,缺省参数,重载函数

C 首先写一段代码&#xff1a; #include <stdio.h>int main() {printf("Hello world\n");return 0; }这段C语言代码在cpp文件中仍可运行。我们了解C是兼容C语言的&#xff0c;C的关键字中就包含了C语言的关键字和自身的关键字。关于关键字&#xff0c;我们简…

LCR 039

. - 力扣&#xff08;LeetCode&#xff09;. - 备战技术面试&#xff1f;力扣提供海量技术面试资源&#xff0c;帮助你高效提升编程技能,轻松拿下世界 IT 名企 Dream Offer。https://leetcode.cn/problems/0ynMMM/ 给定非负整数数组 heights &#xff0c;数组中的数字用来表示…

共享内存和信号灯集练习

#include <mystdio.h> int main(int argc, const char *argv[]) { //创建key值 key_t key ftok("/home/ubuntu",2); if(key<0) { perror("ftok"); return -1; } printf("key%#x\n",key); …