基于gin-vue-admin[gin+gorm]手动实现crud(全)
使用Gin-Vue- Admin框架手动实现crud
在gva框架下自己手动实现一个CRUD的操作,该操作将会结合gen进行探讨学习,具体实现可以看下面代码的实现,项目目录层级分为api层,service层,model层,common层,router层,gen层。
我的这个实现方式有些许不太一样就是,我的修改并非传统的restful风格通过json方式进行传递这个id,也确保安全,所以这里的请求我不会用Get请求。
创建一个Banner
在gva下的server文件夹中找到plugin文件,然后在这里创建一个banner文件夹,我们的手动CRUD实现的代码就放置在这里,查看项目目录结构,banner包的路径是/server/plugin/banner。

model层
在model层中我们分为前端请求的参数request,以及后端返回的只response。在我们的model下会有一个创建表的结构体,也就是对应数据库字段的一个struct
banner的结构体
package modelimport "github.com/flipped-aurora/gin-vue-admin/server/global"type Banner struct {global.GVA_MODELUrl string `json:"url" gorm:"column:url;comment:图片地址"`Path string `json:"path" gorm:"column:path;comment:轮播图跳转地址"`Description string `json:"description" gorm:"column:description;comment:轮播介绍"`
}
model.request层
用于接收前端的参数
package requestimport ("github.com/flipped-aurora/gin-vue-admin/server/plugin/banner/common""github.com/flipped-aurora/gin-vue-admin/server/plugin/banner/model""github.com/flipped-aurora/gin-vue-admin/server/plugin/banner/model/dao""gorm.io/gen"
)type BannerList struct {common.PageInfoUrl string `json:"url" gorm:"column:url;comment:图片地址"`Path string `json:"path" gorm:"column:path;comment:轮播图跳转地址"`Description string `json:"description" gorm:"column:description;comment:轮播介绍"`
}func (r BannerList) BannerList() model.Banner {return model.Banner{Url: r.Url,Path: r.Path,Description: r.Description,}
}type BannerCreate struct {Url string `json:"url" gorm:"column:url;comment:图片地址"`Path string `json:"path" gorm:"column:path;comment:轮播图跳转地址"`Description string `json:"description" gorm:"column:description;comment:轮播介绍"`
}func (r BannerCreate) BannerCreate() model.Banner {return model.Banner{Url: r.Url,Path: r.Path,Description: r.Description,}
}type BannerUpdate struct {common.GetByIdUrl string `json:"url" gorm:"column:url;comment:图片地址"`Path string `json:"path" gorm:"column:path;comment:轮播图跳转地址"`Description string `json:"description" gorm:"column:description;comment:轮播介绍"`
}func (r BannerUpdate) BannerUpdate() model.Banner {return model.Banner{Url: r.Url,Path: r.Path,Description: r.Description,}
}func (r *BannerList) Search() common.GenScopes {return func(tx gen.Dao) gen.Dao {if r.Url != "" {tx = tx.Where(dao.Banner.Url.Eq(r.Url))}if r.Path != "" {tx = tx.Where(dao.Banner.Path.Eq(r.Path))}if r.Description != "" {tx = tx.Where(dao.Banner.Description.Eq(r.Description))}return tx}
}
model.response
返回给前端的一个模型
package responsetype Banner struct {Url string `json:"url" gorm:"column:url;comment:图片地址"`Path string `json:"path" gorm:"column:path;comment:轮播图跳转地址"`Description string `json:"description" gorm:"column:description;comment:轮播介绍"`
}
gen层
可以查看gorm的gen的使用,文档地址:https://gorm.io/gen/ 具体详细的看gorm的文档地址,关于gen的相关使用!!!(可以看目录结构我的文件存放地) gen是基于gorm封装的,在我们最后的banner/main.go中需要装配一下传入db,判断有没有db,没有db的调用需要传入db。
$ go get -u gorm.io/gen
package mainimport ("github.com/flipped-aurora/gin-vue-admin/server/plugin/banner/model""os""path/filepath""gorm.io/gen"
)// generate code
func main() {// 获取当前文件夹路径pwd, _ := os.Getwd()g := gen.NewGenerator(gen.Config{// 文件输出的位置(根据自己的情况而定)OutPath: filepath.Join(pwd, "plugin", "banner", "model", "dao"),// 输出的文件名OutFile: "query.go",// 输出模式Mode: gen.WithDefaultQuery | gen.WithQueryInterface,FieldCoverable: true,WithUnitTest: false,})// 挂在自己的结构体在这里(根据自己的业务而定)g.ApplyBasic(new(model.Banner),)g.Execute()
}
common层
common层一般是放置一些公共资源需要使用的,比如一些返回信息,雪花算法生成id等。
common.common.go
package commonimport ("gorm.io/gen"
)type GetById struct {ID uint `json:"id" form:"id"`
}type GetByIds struct {IDs []uint `json:"ids" form:"ids"`
}// PageInfo 分页字段
type PageInfo struct {Page int `json:"page" form:"page"` // 页码PageSize int `json:"pageSize" form:"pageSize"` // 每页大小Keyword string `json:"keyword" form:"keyword"` //关键字
}// 分页函数
func (c *PageInfo) Paginate() func(tx gen.Dao) gen.Dao {return func(tx gen.Dao) gen.Dao {switch {case c.PageSize > 100:c.PageSize = 100case c.PageSize <= 0:c.PageSize = 10}offset := (c.Page - 1) * c.PageSizereturn tx.Offset(offset).Limit(c.PageSize)}
}type GenScopes func(tx gen.Dao) gen.Dao// 前端传什么返回什么
type PageResult struct {PageInfoList interface{} `json:"list" swaggertype:"string" example:"interface 数据"`Count int64 `json:"count" swaggertype:"string" example:"int64 总数"`
}// list 返回函数
func NewPageResult(list interface{}, count int64, pageInfo PageInfo) PageResult {if list == nil {return PageResult{PageInfo: PageInfo{Page: pageInfo.Page,PageSize: pageInfo.PageSize,},List: []struct{}{},Count: count,}}return PageResult{PageInfo: PageInfo{Page: pageInfo.Page,PageSize: pageInfo.PageSize,},List: list,Count: count,}
}
common.message.go
存放返回信息还可以自定义一些返回状态码!
package commonconst (SuccessCreate = "创建成功"ErrorCreate = "创建失败"SuccessUpdate = "更新成功"ErrorUpdate = "更新失败"SuccessDelete = "删除成功"ErrorDelete = "删除失败"SuccessDeletes = "批量删除成功"ErrorDeletes = "批量删除失败"SuccessFirst = "查询一条成功"ErrorFirst = "查询一条失败"SuccessList = "查询成功"ErrorList = "查询失败"ErrorCount = "查询条数失败"ErrorRequest = "参数有误"SuccessServer = "服务端返回成功"ErrorServer = "服务端返回失败"
)
service层
这里我一般是用于业务处理。
service.banner.go
package serviceimport ("context""github.com/flipped-aurora/gin-vue-admin/server/plugin/banner/common""github.com/flipped-aurora/gin-vue-admin/server/plugin/banner/model""github.com/flipped-aurora/gin-vue-admin/server/plugin/banner/model/dao""github.com/flipped-aurora/gin-vue-admin/server/plugin/banner/model/request""github.com/pkg/errors"
)var Banner = new(banner)type banner struct{}// List 查询多条
func (b *banner) List(ctx context.Context, info request.BannerList) (entity []*model.Banner, count int64, err error) {query := dao.Q.WithContext(ctx).Bannerquery = query.Scopes(info.Search())count, err = query.Count()if err != nil {return nil, 0, errors.Wrap(err, common.ErrorList)}entity, err = query.Scopes(info.Paginate()).Find()if err != nil {return nil, 0, errors.Wrap(err, common.ErrorCount)}return entity, count, nil
}// First 查询单条
func (b *banner) First(ctx context.Context, info common.GetById) (entity *model.Banner, err error) {query := dao.Q.WithContext(ctx).Bannerentity, err = query.Where(dao.Banner.ID.Eq(info.ID)).First()if err != nil {return nil, errors.Wrap(err, common.ErrorFirst)}return entity, nil
}// Create 新增
func (b *banner) Create(ctx context.Context, info request.BannerCreate) error {create := info.BannerCreate()query := dao.Q.WithContext(ctx).Bannererr := query.Create(&create)if err != nil {return errors.Wrap(err, common.ErrorCreate)}return nil
}// Update 修改
func (b *banner) Update(ctx context.Context, info request.BannerUpdate) error {update := info.BannerUpdate()query := dao.Q.WithContext(ctx).Banner_, err := query.Where(dao.Banner.ID.Eq(info.ID)).Updates(update)if err != nil {return errors.Wrap(err, common.ErrorUpdate)}return nil
}// Delete 单个删除
func (b banner) Delete(ctx context.Context, info common.GetById) error {query := dao.Q.WithContext(ctx).Banner_, err := query.Where(dao.Banner.ID.Eq(info.ID)).Delete()if err != nil {return errors.Wrap(err, common.ErrorDelete)}return nil
}// Deletes 批量删除
func (b *banner) Deletes(ctx context.Context, info common.GetByIds) error {query := dao.Q.WithContext(ctx).Banner_, err := query.Where(dao.Banner.ID.In(info.IDs...)).Delete()if err != nil {return errors.Wrap(err, common.ErrorDeletes)}return nil
}
api层
这里我一般是处理接受前端的请求
api.banner.go
这里与service.banner.go的接口一一对应
package apiimport ("github.com/flipped-aurora/gin-vue-admin/server/plugin/banner/common""github.com/flipped-aurora/gin-vue-admin/server/plugin/banner/model/request""github.com/flipped-aurora/gin-vue-admin/server/plugin/banner/response""github.com/flipped-aurora/gin-vue-admin/server/plugin/banner/service""github.com/gin-gonic/gin""net/http"
)var Banner = new(banner)type banner struct{}func (b banner) List(c *gin.Context) response.Response {var list request.BannerListerr := c.ShouldBindJSON(&list)if err != nil {return response.Response{Code: http.StatusPaymentRequired, Message: common.ErrorRequest}}lists, count, err := service.Banner.List(c.Request.Context(), list)if err != nil {return response.Response{Code: http.StatusInternalServerError, Message: common.ErrorServer}}return response.Response{Code: http.StatusOK,Data: common.NewPageResult(lists, count, list.PageInfo),Message: common.SuccessList,}
}func (b *banner) First(c *gin.Context) response.Response {var info common.GetByIderr := c.ShouldBindJSON(info)if err != nil {return response.Response{Code: http.StatusPaymentRequired, Message: common.ErrorRequest}}data, err := service.Banner.First(c.Request.Context(), info)if err != nil {return response.Response{Code: http.StatusInternalServerError, Message: common.ErrorServer}}return response.Response{Code: http.StatusOK,Data: data,Message: common.SuccessFirst,}
}func (b *banner) Create(c *gin.Context) response.Response {var create request.BannerCreateerr := c.ShouldBindJSON(&create)if err != nil {return response.Response{Code: http.StatusPaymentRequired, Message: common.ErrorRequest}}err = service.Banner.Create(c.Request.Context(), create)if err != nil {return response.Response{Code: http.StatusInternalServerError, Message: common.ErrorCreate}}return response.Response{Code: http.StatusOK, Message: common.SuccessCreate}
}func (b *banner) Update(c *gin.Context) response.Response {var update request.BannerUpdateerr := c.ShouldBindJSON(&update)if err != nil {return response.Response{Code: http.StatusPaymentRequired, Message: common.ErrorRequest}}err = service.Banner.Update(c.Request.Context(), update)if err != nil {return response.Response{Code: http.StatusInternalServerError, Message: common.ErrorUpdate}}return response.Response{Code: http.StatusOK, Message: common.SuccessUpdate}
}func (b *banner) Delete(c *gin.Context) response.Response {var info common.GetByIderr := c.ShouldBindJSON(&info)if err != nil {return response.Response{Code: http.StatusPaymentRequired, Message: common.ErrorRequest}}err = service.Banner.Delete(c.Request.Context(), info)if err != nil {return response.Response{Code: http.StatusInternalServerError, Message: common.ErrorDelete}}return response.Response{Code: http.StatusOK, Message: common.SuccessDelete}
}func (b *banner) Deletes(c *gin.Context) response.Response {var info common.GetByIdserr := c.ShouldBindJSON(&info)if err != nil {return response.Response{Code: http.StatusPaymentRequired, Message: common.ErrorRequest}}err = service.Banner.Deletes(c.Request.Context(), info)if err != nil {return response.Response{Code: http.StatusInternalServerError, Message: common.ErrorDeletes}}return response.Response{Code: http.StatusOK, Message: common.SuccessDeletes}
}
router层
这里是路由注册的地方
router.router.go
package routerimport ("github.com/flipped-aurora/gin-vue-admin/server/middleware""github.com/flipped-aurora/gin-vue-admin/server/plugin/banner/api""github.com/flipped-aurora/gin-vue-admin/server/plugin/banner/response""github.com/gin-gonic/gin"
)type Banner struct {router *gin.RouterGroup
}func NewBanner(router *gin.RouterGroup) *Banner {return &Banner{router}
}func (r Banner) Init() {group := r.router.Group("banner"){ // 不带日志中间件group.POST("list", response.Handler()(api.Banner.List))group.POST("first", response.Handler()(api.Banner.First))}{ // 带日志中间件group.Use(middleware.OperationRecord())group.POST("create", response.Handler()(api.Banner.Create))group.PUT("update", response.Handler()(api.Banner.Update))group.DELETE("delete", response.Handler()(api.Banner.Delete))group.DELETE("deletes", response.Handler()(api.Banner.Deletes))}
}
banner/main.go
package bannerimport ("github.com/flipped-aurora/gin-vue-admin/server/global""github.com/flipped-aurora/gin-vue-admin/server/plugin/banner/model/dao""github.com/flipped-aurora/gin-vue-admin/server/plugin/banner/router""github.com/gin-gonic/gin"
)var Plugin = new(plugin)type plugin struct{}func (p plugin) Register(group *gin.RouterGroup) {router.NewBanner(group).Init()// 这里需要自动装配一下调用dbif global.GVA_DB != nil {dao.SetDefault(global.GVA_DB)}
}func (p plugin) RouterPath() string {return ""
}
相关文章:
基于gin-vue-admin[gin+gorm]手动实现crud(全)
使用Gin-Vue- Admin框架手动实现crud 在gva框架下自己手动实现一个CRUD的操作,该操作将会结合gen进行探讨学习,具体实现可以看下面代码的实现,项目目录层级分为api层,service层,model层,common层ÿ…...
彻底关闭Windows10更新!!
以下四个步骤都需要执行。 一、禁用Windows Update服务 1、同时按下键盘 Win R,然后输入 services.msc ,点击确定。 2、找到 Windows Update 这一项,并双击打开。 3、双击打开它,点击 停止,把启动类型选为 禁用&…...
跨时钟域CDC
https://www.cnblogs.com/icparadigm/p/12794483.html https://www.cnblogs.com/icparadigm/p/12794422.html 亚稳态 是什么 时序逻辑在跳变时,由于异步信号、跨时钟域等原因,不满足setup或hold条件,输出在0和1之间产生振荡。 原因 D触发…...
JavaEE简单示例——Spring的控制反转
简单介绍: 在之前的入门程序中,我们简单的介绍了关于Spring框架中的控制反转的概念,这次我们就来详细的介绍和体验一下Spring中的控制反转的理论和实操。 使用方法: 控制反转(IoC)是面向对象编程中的一个…...
DBT 收购 Transform,指标平台已成现代数据栈关键拼图
今年 2 月初,现代数据技术栈独角兽 DBT 宣布完成对 Transform 的并购。在现代数据栈的体系中,DBT 和 Transform 都扮演着重要角色,DBT 侧重于整个分析链路上的数据转换处理,而 Transform 则聚焦在以指标为中心搭建业务分析应用。 …...
@Value注解取不到值的几种错误
在程序中使用了yml文件,然后把有些参数写在里面作为全局变量,在定时器里面使用,但是后来发现取不到: @Value("${spring.datasource.druid.master.url}") private String url; @Value("${spring.datasource.druid.master.driver-class-name}") private …...
听客户说|东台农商银行:建立健全数据安全管理制度的探索与实践
夯实银行数据安全,需“规划先行、谋定后动”,首要工作是确立管理工作的行动纲要,并据此建立制度保障体系以贯彻纲要,而后才是具体的行动措施和日常检查、监测。从银行数据安全建设实践路径来说,我认为可以用“盘现状、…...
Benchbot环境安装记录
https://github.com/qcr/benchbot 第一次安装这种复合型的环境,包括了各种CUDA/NVIDA驱动、Docker环境、python环境等等。因此,遇到了一大堆的问题,在此记录一下亲测有效的博客: https://zhuanlan.zhihu.com/p/378894743 https:/…...
Barrett模乘与蒙哥马利模乘算法
一、背景 公钥密码学(Public-Key Cryptography, PKC)由Diffie与Hellman于1970年代提出,在现代信息社会中得到了广泛应用。此后基于各种数学困难问题,越来越多的公钥密码算法被设计出来,比如RSA、ElGamal、椭圆曲线ECC算法等。在RSA算法中,模幂(modular exponentiation)…...
slice方法
slice方法与splice方法相比slice方法不会修改原数组一、语法以及描述说明:通过start 和 end对原数组进行浅拷贝(提取 start 至 end 索引的数组元素)语法:Array.slice([start[, end])参数:start : 开始索引end : 结束索…...
DevOps工具集合
简介 DevOps(Development和Operations的组合词)是一组过程、方法与系统的统称,用于促进开发(应用程序/软件工程)、技术运营和质量保障(QA)部门之间的沟通、协作与整合。 它是一种重视“软件开…...
手把手教你安装Linux!!!
文章目录Linux简述它们的区别安装CentOS①下载CentOS②安装Linux有两种方式③下载模拟软件④安装vmware⑤创建虚拟机⑥安装操作系统Linux简述 在国内比较流行的两款Linux发行版本CentOS和ubuntu 它们的区别 ubuntu:页面更加的华丽比较漂亮,它对计算机…...
图像分割(Unet算法学习笔记)
知识提要 数据集使用VOC2012 CNN 卷积神经网络Convolutional Neural Network GPU图像处理单元Graphic Processing Unit)图形处理器 convolution 卷积 ReLU全名Rectified Linear Unit,意思是修正线性单元 bn全称Batch Normalization批标准化 FC全连接神经网络是一种…...
Fortinet 发布《2022下半年度全球威胁态势研究报告》,七大发现值得关注
全球网络与安全融合领域领导者Fortinet(NASDAQ:FTNT),近日发布《2022 下半年度全球威胁态势研究报告》。报告指出,相对于组织攻击面的不断扩大以及全球威胁态势的持续演进,网络犯罪分子设计、优化技术与战术…...
ThinkPHP 6.1 模板篇之循环和选择标签
本文主要介绍在视图模板中,如何使用循环和选择标签去渲染变量及常用循环和选择标签。 目录 循环标签 foreach 标签 for 标签 volist 标签 选择标签 switch 标签 if 标签 范围标签 原生标签 总结 循环标签 foreach 标签 将查找到的数组或数据集ÿ…...
Jetpack太香了,让开发效率提升了不少
作者:Jingle_zhang 第三方App使用Jetpack等开源框架非常流行,在Gradle文件简单指定即可。然而ROM内置的系统App在源码环境下进行开发,与第三方App脱节严重,采用开源框架的情况并不常见。但如果系统App也集成了Jetpack或第三方框架…...
【软考中级信安】第四章--网络安全体系与网络安全模型
1.网络安全体系概述1.1 网络安全体系概念网络安全体系:是网络安全保障系统的最高层概念抽象,是由各种网络安全单元按照一定的规则组成的,共同实现网络安全的目标。1.2 网络安全体系特性整体性:网络安全单元按照一定规则࿰…...
四、GC分析内存调优
文章目录(持续更新中... ...)GC分析&内存调优工具篇JDK自带的工具jconsolejvisualvm第三方工具arthas(重要)jprofiler(收费的)MAT、GChisto、gcviewer、GC Easy(待完善)参数、命…...
如何快速开发一套分布式IM系统
架构说明: 1)CIM 中的各个组件均采用 SpringBoot 构建;2)采用 Netty Google Protocol Buffer 构建底层通信;3)Redis 存放各个客户端的路由信息、账号信息、在线状态等;4)Zookeeper …...
W806|CKLINK LITE|调试|elf文件模板|CSDK|Debug|学习(4):CKLINK调试W806
一、硬件连接 接线方式 (连线颜色供参考,本例中采用图示颜色): 注意:CKLINK LITE的3V3须与W806的3V3相连,或者给W806开发板单独供电,两种方式均可。 否则,会提示“the referenc…...
多模态2025:技术路线“神仙打架”,视频生成冲上云霄
文|魏琳华 编|王一粟 一场大会,聚集了中国多模态大模型的“半壁江山”。 智源大会2025为期两天的论坛中,汇集了学界、创业公司和大厂等三方的热门选手,关于多模态的集中讨论达到了前所未有的热度。其中,…...
springboot 百货中心供应链管理系统小程序
一、前言 随着我国经济迅速发展,人们对手机的需求越来越大,各种手机软件也都在被广泛应用,但是对于手机进行数据信息管理,对于手机的各种软件也是备受用户的喜爱,百货中心供应链管理系统被用户普遍使用,为方…...
通过Wrangler CLI在worker中创建数据库和表
官方使用文档:Getting started Cloudflare D1 docs 创建数据库 在命令行中执行完成之后,会在本地和远程创建数据库: npx wranglerlatest d1 create prod-d1-tutorial 在cf中就可以看到数据库: 现在,您的Cloudfla…...
Cinnamon修改面板小工具图标
Cinnamon开始菜单-CSDN博客 设置模块都是做好的,比GNOME简单得多! 在 applet.js 里增加 const Settings imports.ui.settings;this.settings new Settings.AppletSettings(this, HTYMenusonichy, instance_id); this.settings.bind(menu-icon, menu…...
如何将联系人从 iPhone 转移到 Android
从 iPhone 换到 Android 手机时,你可能需要保留重要的数据,例如通讯录。好在,将通讯录从 iPhone 转移到 Android 手机非常简单,你可以从本文中学习 6 种可靠的方法,确保随时保持连接,不错过任何信息。 第 1…...
【MATLAB代码】基于最大相关熵准则(MCC)的三维鲁棒卡尔曼滤波算法(MCC-KF),附源代码|订阅专栏后可直接查看
文章所述的代码实现了基于最大相关熵准则(MCC)的三维鲁棒卡尔曼滤波算法(MCC-KF),针对传感器观测数据中存在的脉冲型异常噪声问题,通过非线性加权机制提升滤波器的抗干扰能力。代码通过对比传统KF与MCC-KF在含异常值场景下的表现,验证了后者在状态估计鲁棒性方面的显著优…...
如何应对敏捷转型中的团队阻力
应对敏捷转型中的团队阻力需要明确沟通敏捷转型目的、提升团队参与感、提供充分的培训与支持、逐步推进敏捷实践、建立清晰的奖励和反馈机制。其中,明确沟通敏捷转型目的尤为关键,团队成员只有清晰理解转型背后的原因和利益,才能降低对变化的…...
面试高频问题
文章目录 🚀 消息队列核心技术揭秘:从入门到秒杀面试官1️⃣ Kafka为何能"吞云吐雾"?性能背后的秘密1.1 顺序写入与零拷贝:性能的双引擎1.2 分区并行:数据的"八车道高速公路"1.3 页缓存与批量处理…...
土建施工员考试:建筑施工技术重点知识有哪些?
《管理实务》是土建施工员考试中侧重实操应用与管理能力的科目,核心考查施工组织、质量安全、进度成本等现场管理要点。以下是结合考试大纲与高频考点整理的重点内容,附学习方向和应试技巧: 一、施工组织与进度管理 核心目标: 规…...
电脑桌面太单调,用Python写一个桌面小宠物应用。
下面是一个使用Python创建的简单桌面小宠物应用。这个小宠物会在桌面上游荡,可以响应鼠标点击,并且有简单的动画效果。 import tkinter as tk import random import time from PIL import Image, ImageTk import os import sysclass DesktopPet:def __i…...
