golang中xorm的基本使用

本文详细介绍了如何使用Go语言中的XORM ORM框架进行数据库操作,包括增删改查等基本功能,并结合gin框架实现了RESTful API。此外,还深入探讨了事务处理及回滚的实现方式。

 

    简单的用法

package main

import (
	_ "github.com/go-sql-driver/mysql"
	"github.com/go-xorm/xorm"
	"log"
)

//定义结构体(xorm支持双向映射)
type User struct {
	User_id    int64   `xorm:"pk autoincr"` //指定主键并自增
	Name       string  `xorm:"unique"`      //唯一的
	Balance    float64
	Time       int64 `xorm:"updated"` //修改后自动更新时间
	Creat_time int64   `xorm:"created"` //创建时间
	//Version    int     `xorm:"version"` //乐观锁
}

//定义orm引擎
var x *xorm.Engine

//创建orm引擎
func init() {
	var err error
	x, err = xorm.NewEngine("mysql", "root:root@tcp(127.0.0.1:3306)/xorm?charset=utf8")
	if err != nil {
		log.Fatal("数据库连接失败:", err)
	}
	if err := x.Sync(new(User)); err != nil {
		log.Fatal("数据表同步失败:", err)
	}
}

//增
func Insert(name string, balance float64) (int64, bool) {
	user := new(User)
	user.Name = name
	user.Balance = balance
	affected, err := x.Insert(user)
	if err != nil {
		return affected, false
	}
	return affected, true
}

//删
func Del(id int64) {
	user := new(User)
	x.Id(id).Delete(user)
}

//改
func update(id int64, user *User) bool {
	affected, err := x.ID(id).Update(user)
	if err != nil {
		log.Fatal("错误:", err)
	}
	if affected == 0 {
		return false
	}
	return true
}

//查
func getinfo(id int64) *User {
	user := &User{User_id: id}
	is, _ := x.Get(user)
	if !is {
		log.Fatal("搜索结果不存在!")
	}
	return user
}

   

    在gin中的用法

package main

import (
	"github.com/gin-gonic/gin"
	"./models"
	"strconv"
)

//添加操作
func insert(c *gin.Context) {
	name := c.Query("name")
	if name == "" {
		c.JSON(200, gin.H{"msg": "name不得为空!"})
		return
	}

	money := c.Query("money")
	if money == "" {
		c.JSON(200, gin.H{"msg": "money不得为空!"})
		return
	}

	Balance, _ := strconv.ParseFloat(money, 64)
	//添加
	user := models.User{}
	user.Name = name
	user.Balance = Balance
	rel, err := models.X.Insert(user)

	if rel == 0 || err != nil {
		c.JSON(200, gin.H{"msg": "添加错误", "err": err, "rel": rel})
	} else {
		c.JSON(200, gin.H{"msg": "添加成功"})
	}
}

//查询单个操作
func get(c *gin.Context) {
	id := c.Query("id")
	if id == "" {
		c.JSON(200, gin.H{"msg": "id不得为空!"})
		return
	}
	//string转int64
	ids, _ := strconv.ParseInt(id, 10, 64)
	//查询1
	//user := &User{User_id: ids}
	//rel, err := models.X.Get(user)
	//查询2
	user := &models.User{}
	rel, err := models.X.Where("user_id = ?", ids).Get(user)

	if !rel || err != nil {
		c.JSON(200, gin.H{"msg": "查询错误"})
	} else {
		c.JSON(200, gin.H{"user": user})
	}
}

//查询多条操作
func find(c *gin.Context) {
	users := make(map[int64]models.User)
	err := models.X.Find(&users)
	if err != nil {
		c.JSON(200, gin.H{"msg": err})
	}
	c.JSON(200, gin.H{"msg": users})
}

//修改操作
func updates(c *gin.Context) {
	id := c.Query("id")
	if id == "" {
		c.JSON(200, gin.H{"msg": "id1不得为空!", "id": id})
		return
	}
	ids, _ := strconv.ParseInt(id, 10, 64)

	name := c.Query("name")
	if name == "" {
		c.JSON(200, gin.H{"msg": "name不得为空!"})
		return
	}

	balance := c.Query("balance")
	if balance == "" {
		c.JSON(200, gin.H{"msg": "balance不得为空!"})
		return
	}
	money, _ := strconv.ParseFloat(balance, 64)
	//修改
	user := models.User{}
	user.Name = name
	user.Balance = money
	rel, err := models.X.Id(ids).Update(user)

	if rel == 0 || err != nil {
		c.JSON(200, gin.H{"msg": "修改错误!", "rel": rel, "err": err, "user": user})
	} else {
		c.JSON(200, gin.H{"mag": "修改成功"})
	}
}

//删除操作
func delte(c *gin.Context) {
	id := c.Query("id")
	if id == "" {
		c.JSON(200, gin.H{"msg": "id1不得为空!", "id": id})
		return
	}
	//string转化int64
	ids, _ := strconv.ParseInt(id, 10, 64)
	//删除
	user := models.User{}
	rel, err := models.X.Id(ids).Delete(user)

	if rel == 0 || err != nil {
		c.JSON(200, gin.H{"msg": "删除错误!", "rel": rel, "err": err, "user": user})
	} else {
		c.JSON(200, gin.H{"mag": "删除成功"})
	}
}

//事务的提交以及回滚
func gun(c *gin.Context) {
	//创建session
	session := models.X.NewSession()
	defer session.Close()
	//创建事务
	err := session.Begin()
	if err != nil {
		c.JSON(200, gin.H{"err": err})
		return
	}
	//操作事务,失败并回滚(模拟购物车结算情景)
	car_id := c.Query("car_id")
	if car_id == "" {
		c.JSON(200, gin.H{"msg": "car_id1不得为空!", "car_id": car_id})
		return
	}

	//查找购物车中的商品id
	ids, _ := strconv.ParseInt(car_id, 10, 64)
	car := &models.Car{Car_id: ids}
	models.X.Get(car)

	/**
	*	goods表库存减去销量
	*/
	//查询商品
	goods := &models.Goods{Goods_id: car.Goods_id}
	models.X.Get(goods)
	//更新库存
	good := models.Goods{}
	good.Stock = goods.Stock - car.Num
	rel4, err4 := session.ID(car.Goods_id).Update(good)
	if rel4 == 0 || err4 != nil {
		session.Rollback()
		c.JSON(200, gin.H{"err4": err4, "rel4": rel4, "carid": car.Goods_id, "goodsid": goods.Goods_id, "Stock": good.Stock})
		return
	}

	/**
	*	用户扣费
	*/
	//查询用户
	user := &models.User{User_id: car.User_id}
	models.X.Get(user)
	//更新价格
	user_up := models.User{}
	user_up.Balance = user.Balance - car.Total_price
	rel1, err1 := session.ID(car.User_id).Update(user_up)
	if err1 != nil || rel1 == 0 {
		session.Rollback()
		c.JSON(200, gin.H{"err1": err1, "rel1": rel1})
		return
	}

	/**
	*	删除用户的购物车信息
	*/
	rel2, err2 := session.Delete(car)
	if err2 != nil || rel2 == 0 {
		session.Rollback()
		c.JSON(200, gin.H{"err2": err2, "rel2": rel2})
		return
	}
	if user_up.Balance <= 0 {
		session.Rollback()
		c.JSON(200, gin.H{"msg": "余额不足"})
		return
	}

	err3 := session.Commit()
	if err3 != nil {
		c.JSON(200, gin.H{"err3": err3})
		return
	}
	c.JSON(200, gin.H{"msg": "用户扣费成功"})
}

func update_goods(c *gin.Context) {
	id := c.Query("id")
	if id == "" {
		c.JSON(200, gin.H{"msg": "id1不得为空!", "id": id})
		return
	}
	//string转换int64
	ids, err := strconv.ParseInt(id, 10, 64)

	goods_name := c.Query("goods_name")
	if goods_name == "" {
		c.JSON(200, gin.H{"msg": "goods_name不得为空!", "goods_name": goods_name})
		return
	}

	price := c.Query("price")
	if price == "" {
		c.JSON(200, gin.H{"msg": "price不得为空!", "price": price})
		return
	}
	prices, _ := strconv.ParseFloat(price, 64)

	stock := c.Query("stock")
	if stock == "" {
		c.JSON(200, gin.H{"msg": "stock不得为空!", "stock": stock})
		return
	}
	stocks, _ := strconv.ParseInt(stock, 10, 64)

	//修改
	goods := models.Goods{}
	goods.Stock = stocks
	goods.Goods_name = goods_name
	goods.Price = prices
	rel, err := models.X.ID(ids).Update(goods)
	if rel == 0 || err != nil {
		c.JSON(200, gin.H{"msg": "修改失败", "err": err, "stocks": stocks, "goods_name": goods_name, "prices": prices, "id": id})
	} else {
		c.JSON(200, gin.H{"msg": "修改成功"})
	}
}

func shiwu(c *gin.Context) {
	session := models.X.NewSession()
	defer session.Close()

	err := session.Begin()
	user1 := models.User{Name: "xiaoxiao1", Balance: 100}
	_, err = session.Insert(&user1)
	if err != nil {
		return
	}

	session.Rollback()
	data := make(map[string]interface{})
	data["msg"] = "错误"
	c.JSON(200, session)
	c.JSON(200, data)
	return

	//提交
	err = session.Commit()
	if err != nil {
		return
	}
}

func main() {
	r := gin.Default()
	r.GET("/insert", insert)
	r.GET("/get", get)
	r.GET("/find", find)
	r.GET("/updates", updates)
	r.GET("/delte", delte)
	r.GET("/update_goods", update_goods)
	r.GET("/gun", gun)
	r.GET("/shiwu", shiwu)
	r.Run(":88")
}

需要填坑的是:这里面我使用事务一直实现不了回滚,再次细致阅读文档才发现,

而关于innodb的设置方法,这里有一个很好的教程;https://blog.youkuaiyun.com/leejianjun/article/details/72467983

 

Golang使用 XORM 框架操作 MySQL 数据库时,处理 `POINT` 类型需要特别注意类型定义和映射方式。MySQL 的 `POINT` 类型用于表示地理空间数据中的点,通常以 `POINT(x, y)` 的形式存储经纬度坐标。 为了在 XORM 中正确映射 `POINT` 类型,可以通过自定义结构体字段类型并使用 XORM 的标签配置实现。 ### 映射方式 MySQL 中的 `POINT` 类型可以映射为 Go 中的结构体或字节数组。常见的做法是将其映射为 `[]byte` 或使用 WKT(Well-Known Text)格式进行解析和存储。 #### 示例定义 ```go type Location struct { ID int64 Name string Geo []byte `xorm:"geometry"` // 映射 MySQL 的 POINT 类型 Created time.Time } ``` 在 MySQL 中,`POINT` 类型字段通常使用 `GEOMETRY` 类型存储,因此在 XORM 中通过 `xorm:"geometry"` 标签进行映射。数据库操作时,可以使用 `ST_GeomFromText` 和 `ST_AsText` 函数将 WKT 格式与 `POINT` 类型相互转换。 #### 插入 POINT 数据 插入数据时,可以使用 SQL 函数将 WKT 格式字符串转换为 `POINT` 类型: ```go session.Exec("INSERT INTO location (name, geo) VALUES (?, ST_GeomFromText(?))", "Point A", "POINT(120 30)") ``` #### 查询 POINT 数据 查询时,可以将 `POINT` 转换为 WKT 格式字符串以便解析: ```go var location Location has, err := session.SQL("SELECT id, name, ST_AsText(geo) as geo FROM location WHERE name = ?", "Point A").Get(&location) ``` ### 注意事项 - `POINT` 类型在 Go 中通常以二进制形式存储在 `[]byte` 中,也可以通过自定义类型进行封装和解析。 - 若需对地理空间数据进行复杂操作(如距离计算、范围查询),建议使用支持空间索引和函数的 MySQL 版本(如 5.7+)。 - XORM 对 `GEOMETRY` 类型的支持依赖于底层数据库驱动,确保使用支持 `GEOMETRY` 类型的 MySQL 驱动(如 `github.com/go-sql-driver/mysql`)[^4]。 ### 示例代码 以下是一个完整的示例代码: ```go package main import ( "fmt" "log" "time" _ "github.com/go-sql-driver/mysql" "xorm.io/xorm" ) type Location struct { ID int64 Name string Geo []byte `xorm:"geometry"` // 映射 MySQL 的 POINT 类型 Created time.Time } func main() { engine, err := xorm.NewEngine("mysql", "root:password@/testdb?charset=utf8mb4") if err != nil { log.Fatal(err) } // 同步表结构 err = engine.Sync2(new(Location)) if err != nil { log.Fatal(err) } // 插入 POINT 数据 _, err = engine.Exec("INSERT INTO location (name, geo) VALUES (?, ST_GeomFromText(?))", "Point A", "POINT(120 30)") if err != nil { log.Fatal(err) } // 查询 POINT 数据 var location Location has, err := engine.SQL("SELECT id, name, ST_AsText(geo) as geo FROM location WHERE name = ?", "Point A").Get(&location) if err != nil { log.Fatal(err) } if has { fmt.Printf("Location: %+v\n", location) } } ``` ###
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值