当前位置: 首页 > news >正文

Golang sql 事务如何进行分层

在写代码过程中遇到了需要使用gorm执行sql事务的情况,研究了一下各位大佬的实现方案,结合了自身遇到的问题,特此记录。



代码架构介绍

.
├── apis
├── config
├── internal
│   ├── constant
│   ├── controller
│   ├── logic
│   ├── model
│   ├── repo
│   ├── router
│   └── service
├── library
├── pkg
├── scripts

目录结构其实很简单,主要参考了goframe的架构。internal/logic放逻辑代码,internal/repo是dao层,负责与数据库进行交互。



演变过程

最开始的时候是直接把对事务操作放在repo层中了。比如说有两张表,一张用户消费记录表,一张用户积分表,在用户消费完成后就要增加对应的积分。那么在repo层就会有一个函数负责开启事务,写消费记录表,写积分表,提交事务。在logic层中只需要调用这个函数就可以同时完成这两个操作。


看起来很美好,逻辑分的很清晰,但是这么做其实有个问题。如果logic层中有逻辑只操作消费记录表呢,或者用户消费积分只操作积分表呢,或者又有其他的表需要进行联合操作。这种写法会在repo层不断增加一个又一个函数,导致函数越来越多,因为承载了过多的业务逻辑。


发现这种情况之后,我们想可不可以把业务逻辑从repo层抽离,放在logic层进行处理,repo层只做简单的增删改查。那么repo层就可以只实现几个基础的函数,Create(),Update(),Selete()等,然后在logic层通过调用这几个函数实现复杂的逻辑操作。还是之前那个例子,比如说先消费再增加积分就可以变成对两个函数调用。

	// logic 层func buy() {tx := db.begin()cosume.Create(tx)point.Update(tx)tx.commit()}

分层是明确了,但是又引出了新的问题,就是如果我想使用事务,那么就需要在logic层对事务进行开启和提交,并且logic层还需要保存db的连接(用于开启事务),并且将tx传给repo层进行操作,这不合理。logic应该专注于代码逻辑的处理,而不是如何开启一个数据库事务。
目标很明确,如何让logic层只关注与逻辑的操作,而不是开启事务。上文也说到repo层只做一些简单的增删改查的操作,在repo里实现是不可能了,那么只能采取终极方案,在logic和repo之间增加一层中间层,专门用于开启事务。
这个中间层更像一个管理层,用于管理具体操作数据库的repo类和事务的操作,当需要开启事务时,logic只需要编写好业务逻辑,然后调用管理层的接口。管理层负责开启事务,调用logic层编写好的逻辑,提交/回滚事务即可。
这样logic层既不用处理事务相关的任务,repo层也不需要处理复杂的业务逻辑。



实现方案

总结一下上面所说,我们需要实现一个管理类,在管理类里面提供一个事务接口,这个接口的入参有一个func,这个func就是logic层编写好的各种逻辑,为了将tx传递给repo,我们是将其放在了ctx中。

管理层示例

Internal/repo/transaction.go

这个代码参考的时 gorm.Transaction(),做了简单修改。注释写的很详细了。

// Mysql Mysql数据库
type Mysql struct {db *gorm.DB
}func (m *Mysql) Transaction(ctx context.Context, fc func(txCtx context.Context) error) error {panicked := truevar err error// 拿到 ctx 里面的 db 连接,如果没有则使用默认的 db 连接db := m.getDB(ctx)// ...// 使用这个连接开启事务tx := db.WithContext(ctx).Begin()if tx.Error != nil {return tx.Error}defer func() {// Make sure to rollback when panic, Block error or Commit errorif panicked || err != nil {tx.Rollback()}}()// 将事务的 tx 写入 ctx 中,为了真正操作数据库的函数拿到 txtxCtx := generateContextWithDB(ctx, tx)// 调用 logic 层传入的 funcif err = fc(txCtx); err == nil {panicked = false// 如果没有报错就提交事务return tx.Commit().Error}panicked = false// 把事务内的报错转发出去return err
}

调用示例

/internal/logic/manager.go

func (m *manager) Buy(ctx context.Context) error {// 调用 Transaction 函数,txCtx 则为带有 tx 的 ctxif err := m.mysql.Transaction(ctx, func(txCtx context.Context) {// 这里只需要实现对应的业务即可,无需关注事务的开启和提交/回滚逻辑m.mysql.Consume(txCtx).Create()m.mysql.Point(txCtx).Update()}); err != nil {// do something}return nil
}

从 manager 这个函数的角度来看,整个事务执行的逻辑为,通过 Transaction 第一个参数 ctx 获取要执行事务的 db 连接,开启事务后将 tx 封到 context 中,然后传入 Transaction 第二个参数 func() 的入参中。通过将 txCtx 传入到不同的 repo 类中来实现各个 repo 使用同一个 tx 进行事务的操作。Transaction 函数保证了中间有任何错误都会进行回滚和无错误的提交操作。

Consume()和Point()做的是解析 txCtx 中的 db 连接,然后 new 一个repo 类返回。getDB() 负责返回 ctx 里的 db 接。

func (m *Mysql) Consume(ctx context.Context) ConsumeRepo {return NewConsumeRepo(m.getDB(ctx))
}

整体的代码逻辑就是这样,如果需要支持多个引擎,其实可以考虑抽出一个interface,各个引擎实现这个 interface 的接口即可。



gorm 一些写法

多表联查

我们的表设计的不是很规范,导致表和表之间基本上没有什么关联,外键也没有,所以没有办法使用gorm提供的preload,采取的是手动join的方式。

func (c *ConsumePoint) SelectForUpdate(ctx context.Context) (*model.ConsumeAndPoint, error) {// 接收数据的结构var record model.ConsumeAndPointif err := c.db.WithContext(ctx).// 主表Table("t_consume").// 返回什么Select("t_consume.*, t_point.f_point").// 连接方式Joins("join t_point on t_consume.f_user_id = t_point.f_user_id").// 只查询一条数据First(&record).Error; err != nil {// do something}return &record, nil
}

select for update

先读后更新的数据竞争且应该将加锁操作放到事务中,防止锁被自动释放,其实主要就在于 Set(“gorm:query_option”, “FOR UPDATE”) 这一行。如果采用上面多表联查的方式,设置了 FOR UPDATE 后两张表的内容都会有X锁,直到事务提交。可以用这个特性来搞分布式的竞争更新。

func UpdateUser(db *gorm.DB, id int64) error {tx := db.Begin()defer func() {if r := recover(); r != nil {tx.Rollback()}}()if err := tx.Error; err != nil {return err}user := User{}// 锁住指定 id 的 User 记录if err := tx.Set("gorm:query_option", "FOR UPDATE").First(&user, id).Error; err != nil {tx.Rollback()return err}// 更新操作...// commit事务,释放锁if err := tx.Commit().Error; err != nil {return err}return nil
}

相关文章:

Golang sql 事务如何进行分层

在写代码过程中遇到了需要使用gorm执行sql事务的情况,研究了一下各位大佬的实现方案,结合了自身遇到的问题,特此记录。 代码架构介绍 . ├── apis ├── config ├── internal │ ├── constant │ ├── controller │ ├──…...

linux系统openssh升级

linux系统openssh升级 说明 整个过程不需要卸载原先的openssl包和openssh的rpm包。本文的环境都是系统自带的openssh,没有经历过手动编译安装方式。如果之前有手动编译安装过openssh,请参照本文自行测试是否能成功。 如果严格参照本文操作,保…...

力扣-求关注者的数量

大家好,我是空空star,本篇带大家了解一道简单的力扣sql练习题。 文章目录前言一、题目:1729. 求关注者的数量二、解题1.正确示范①提交SQL运行结果2.正确示范②提交SQL运行结果3.正确示范③提交SQL运行结果4.正确示范④提交SQL运行结果5.正确…...

近红外荧光染料修饰氨基IR 825 NH2,IR 825-Amine,IR-825 NH2

IR 825 NH2,IR 825-NH2,IR825 Amine,IR825-Amine,新吲哚菁绿-氨基,荧光染料修饰氨基产品规格:1.CAS号:N/A2.包装规格:10mg,25mg,50mg,包装灵活&am…...

Android Crash和ANR监控

文章目录一、Crash1.1 概念1.2 类型二、ANR2.1 概念2.2 类型2.2.1 KeyDispatchTimeout(常见)2.2.2 BroadcastTimeout2.2.3 ServiceTimeout2.2.4 ContentProviderTimeout三、测试中如何关注3.1 Crash测试关注方法3.2 ANR测试关注方法四、如何记录与处理4.…...

【02 赖世雄英语语法:复句的语法】

复句的语法复句:把单句 连在一起(标点符号,连词,关系词)1. 连接符号1.1 破折号 — :补充说明,同位语1.2 冒号 : (同位语)1.3 分号 ; ( , 连词)&am…...

北斗导航 | 多参考一致性监测算法(MRCC)(附伪码)—— B值计算

===================================================== github:https://github.com/MichaelBeechan CSDN:https://blog.csdn.net/u011344545 ===================================================== MRCC 用于接收机失效检查与排除。在进行 MRCC 之前,先判断 4 台接收机…...

数字孪生与 UWB 人员定位:双剑合璧的智能物联新时代

人员定位是指利用各种定位技术对人员在特定场所的位置进行准确定位的技术。人员定位技术主要应用于需要实时监控、管理和保障人员安全的场所,如大型厂区、仓库、医院、学校、商场等。人员定位技术的应用范围非常广泛,例如:-在工厂生产线上&am…...

奇点云DataSimba发版全解析:“企业级”版本升级,提供最佳组合

近日,奇点云发布数据云产品商业化版本的全新升级:DataSimba(数据云平台)提供极速版、专业版、旗舰版、红旗版,可靠性、可用性、可服务性再进阶,四大版本满足不同企业选择。 「乐高式DIY」or「最佳组合」&am…...

2-7 SpringCloud快速开发入门: Eureka 注册中心高可用集群搭建

接上一章节Eureka 服务注册中心发现与消费服务,这里讲讲Eureka 注册中心高可用集群搭建 Eureka 注册中心高可用集群搭建 Eureka 注册中心高可用集群就是各个注册中心相互注册 Eureka Server的高可用实际上就是将自己作为服务向其他服务注册中心注册自己&#xff0c…...

STL中的函数对象

STL-函数对象 函数对象概念 重载函数调用操作符的类,其对象常称为函数对象函数对象使用重载的()时,行为类似函数调用,也叫仿函数 本质 函数对象(仿函数)是一个类,不是一个函数—修改算法策略—采用虚拟对象调用 函数对象的使用理…...

linux下libevent的编译安装

1,官网下载最新的,https://libevent.org/2,将文件解压,虚拟机可以右键解压,也可以用命令解压,tar zxvf libevent.tar.gz,进行解压缩。这里压缩包的名称只是举例,实际它还会带上版本号…...

深度学习部署笔记(十): CUDA RunTime API-2.2流的学习

1. 流的定义 流(Stream)是一个基于上下文(Context)的任务管道抽象,是一组由GPU依次执行的CUDA操作序列,其中每个操作可能会使用或产生数据。在一个上下文中可以创建多个流,每个流都拥有自己的任…...

[ROC-RK3568-PC] [Firefly-Android] 10min带你了解I2C的使用

🍇 博主主页: 【Systemcall小酒屋】🍇 博主追寻:热衷于用简单的案例讲述复杂的技术,“假传万卷书,真传一案例”,这是林群院士说过的一句话,另外“成就是最好的老师”,技术…...

工作记录:举步维艰的在线 word 之旅 - tinymce

项目中需要实现 “在线编辑 word 模板” 的功能,我打算使用富文本组件 tinymce ,因为业务需求比较特殊,研究一下 tinymce 是否能实现。 如何在 vue 项目中引用 tinymce,可以看另一篇文章 《在 vue 项目中使用 tinymce》 &#x…...

动态规划编译距离

583. 两个字符串的删除操作方法:dp状态表示:以i-1和j-1为结尾的字符串world1和world2,抵达相同的字符串所需的最少操作数属性:最小值状态计算:world1[i-1]和world2[j-1]相同dp[i][j] dp[i-1][j-1];world1[i-1]和world…...

Netty 教程 – 解码器详解

TCP以流的方式进行数据传输,上层的应用为了对消息进行区分,往往采用如下方式 固定消息长度,累计读取到长度和定长LEN的报文后,就认为读取到了个完整的消息,然后将计数器位置重置在读取下一个报文内容将回车换行符作为…...

Allegro如何自动添加测试点操作指导

Allegro如何自动添加测试点操作指导 在做PCB设计的时候,在一些应用场合下需要给PCB上的网络添加测试点,如下图 测试点除了可以手动逐个添加之外,Allegro还支持自动添加测试点,具体操作如下 点击Manufacture点击Testprep...

【CSS】CSS 背景设置 ③ ( 背景位置-长度值设置 | 背景位置-长度值方位值同时设置 )

文章目录一、背景位置-长度值设置二、背景位置-长度值方位值同时设置三、完整代码示例一、背景位置-长度值设置 长度值设置 效果展示 : 设置背景位置为具体值 10px 50px : 粉色区域是盒子的区域 , 图片背景位于盒子位置 x 轴方向 10 像素 , y 轴方向 50 像素 ; 在水平方向上 ,…...

AbTest —— 不同场景下的应用模式

文章目录不同人群眼中的 AbTestAbTest 不同的功能倚重用户关联性弱,经典场景为 Feed - 部门组织形式大多非垂直业务用户关联性强,经典场景为 垂类/工具类APP;部门组织形式大多为垂直业务康为定律-组织决定产品形态不同应用模式下服务构建开机…...

fast-api 一款快速将spring的bean发布成接口并生产对应swagger文档调试的轻量级工具

fast-api简介背景开发痛点:分析需求实战fast-api快速上手1. 引入依赖2. FastApiMapping标记service对象3. swagger2/knife4j 在线测试进阶使用开启调试模式支持指定类或包目录发布如何关闭fast-api自定义fast-api的前缀写在最后简介 fast-api 一款快速将spring的bean(service)发…...

以公益之名 让人类发现数学之美

目录 1.品牌理念高举高打 2.创新赛制 赋能品牌 3.全球化的品牌传播 9月26日,2022阿里巴巴全球数学竞赛获奖名单公布,4座金杯分别由平均年龄25岁,来自美国麻省理工学院、美国布朗大学、北京大学在读数学博士斩获。77位获奖者中00后超五成引热…...

JUC并发编程之HashMap(jdk1.7版本)-底层源码探究

目录 JUC并发编程之HashMap(jdk1.7版本)-底层源码探究 HashMap底层源码 - jdk1.7 基本概念 -采取层层递进,问答式 存储Key-Value的结构 常量和成员变量 构造方法 put方法 inflateTable方法 hash方法 indexFor方法 addEntry方法 resize方法 createEntry…...

QT Q_OBJECT 和 signals/slots

Q_OBJECT宏展开 #define Q_OBJECT \ public: \QT_WARNING_PUSH \Q_OBJECT_NO_OVERRIDE_WARNING \static const QMetaObject staticMetaObject; \virtual const QMetaObject *metaObject() const; \virtual void *qt_metacast(const char *); \virtual int qt_metacall(QMetaOb…...

APM新添加UAVCAN设备

简介 UAVCAN是一种轻量级协议,旨在通过CAN总线在航空航天和机器人应用中实现可靠通信。要实现通信,最基本需要data_type_ id, signature、数据结构、设备程序初始化。 添加设备数据结构文件(.uavcan格式) 1.在以下路径添加设备数据结构文件,根据设备类…...

【C++】string类基本用法

文章目录string类基本用法1. 为什么要学习string类?1.1 C语言中的字符串2. 标准库中的string类2.1 string类2.2 string类的常用接口说明小试牛刀1. 仅仅反转字母2. 字符串中第一个唯一字符3. 字符串中最后一个单词的长度string类基本用法 1. 为什么要学习string类&…...

KDZD耐电压高压击穿强度测试仪

一、技术参数 01、输入电压: 交流 220 V。 02、输出电压: 交流 0--50KV ; 直流 0—50kv 。 03、电器容量:3KVA。 04、高压分级:0—50KV,(全程可调)。 05、升压速率:0.1KV/s-…...

数组和指针面试题的补充(细的抠jio)

生命是一条艰险的峡谷&#xff0c;只有勇敢的人才能通过。 ——米歇潘 说明&#xff1a;用的vs都是x86的环境&#xff0c;也就是32位平台。 建议&#xff1a;对于难题来说&#xff0c;一定要配合画图来解决问题。 第一题&#xff1a; #include<stdio.h> int…...

Java多线程基础

文章目录Java多线程基础一、什么是进程与线程&#xff1f;二、线程和进程的区别【重点】三、线程的创建方式【重点】1. 继承Thread类2. 实现Runnable接口3. lambda 表达式四、Thread的常见属性线程中断自己定义一个标志位Thread类提供的静态方法线程的状态Java多线程基础 一、…...

爆品分析第5期 | 一条视频带货3700+,这款斋月不锈钢厨具套装火了!

俗话说民以食为天&#xff0c;吃在任何一种文化中都占据重要的位置&#xff0c;要做出一道美味佳肴&#xff0c;除了食材、烹饪者的自身厨艺之外&#xff0c;还少不了一口好锅。新冠疫情以来&#xff0c;全世界范围内的封闭让很多人养成了居家做饭的习惯&#xff0c;不仅为厨具…...

团队管理的七个要点

要掌握团队管理的要点和做好团队管理工作&#xff0c;不是一件容易的事&#xff0c;但也远非想象中那么难。首先&#xff0c;我个人比较推荐所有团队管理者都能阅读下《经理人参阅&#xff1a;团队管理》&#xff08;注意该书仅可其官网获得&#xff09;这本佳作。相信会为你带…...

Go语言容器之map、list和nil

一、map map和C中map一样&#xff0c;里面存放的是key-value键值对在Go中map是引用类型&#xff0c;声明语法&#xff1a;var map变量名 map[key的类型]value的类型package mainimport "fmt"func main() {var mp map[string]intmpls : map[string]int{"one&quo…...

软件测试的案例分析 - 闰年1

&#xff08;这是关于博客质量分的测试 https://www.csdn.net/qc) 我们谈了不少测试的名词, 软件是人写的, 测试计划和测试用例也是人写的, 人总会犯错误。错误发生之后, 总有人问: 为什么这个bug 没有测出来啊?! 我们看看一类简单的bug是如何发生的&#xff0c;以及如何预防…...

【强化学习】强化学习数学基础:值函数近似

值函数近似Value Function ApproximationMotivating examples: curve fittingAlgorithm for state value estimationObjective functionOptimization algorithmsSelection of function approximatorsIllustrative examplesSummary of the storyTheoretical analysisSarsa with …...

JVM系列——Java与线程,介绍线程原理和操作系统的关系

并发不一定要依赖多线程(如PHP中很常见的多进程并发)。 但是在Java里面谈论并发&#xff0c;基本上都与线程脱不开关系。因此我们讲一下从Java线程在虚拟机中的实现。 线程的实现 线程是比进程更轻量级的调度执行单位。 线程的引入&#xff0c;可以把一个进程的资源分配和执行调…...

C++打开文件夹对话框之BROWSEINFO

头文件 #include <shlobj.h> #include <windows.h> #include <stdio.h> using namespace std; 案例 string chooseFile(void) {//用户选择的路径&#xff0c;可以是TCHAR szBuffer[MAX_PATH] {0};然后再使用TCHAR 转char字符串&#xff0c;此处可以直接使…...

Nuxt项目配置、目录结构说明-实战教程基础-Day02

Nuxt项目配置、目录结构说明-实战教程基础-Day02一、Nuxt项目结构1.1资源目录1.2 组件目录1.3 布局目录1.4 中间件目录1.5 页面目录1.6 插件目录1.7 静态文件目录1.8 Store 目录1.9 nuxt.config.js 文件1.10 package.json 文件其他&#xff1a;别名二、项目配置2.1 build2.2 cs…...

单链表的头插,尾插,头删,尾删等操作

前言顺序表要求是具有连续的物理空间&#xff0c;并且数据的话是在这些空间当中是连续的存储。但这样会带来很多问题&#xff0c;比如说在头部或者说中间插入的话&#xff0c;效率不是很高&#xff1b;并且申请空间可能需要扩容&#xff0c;并且越往后一般来说都是异地扩容&…...

Qt扫盲-QProcess理论总结

QProcess理论使用总结一、概述二、使用三、通过 Channel 通道通信四、同步进程API五、注意事项1. 平台特性2. 不能实时读取一、概述 QProcess 其实更多的是与外面进程进行交互的一个工具类&#xff0c;通过这个类来启动外部进程&#xff0c;获取这个进程的标准输出&#xff0c…...

JAVA进阶 —— Steam流

目录 一、 引言 二、 Stream流概述 三、Stream流的使用步骤 1. 获取Stream流 1.1 单列集合 1.2 双列集合 1.3 数组 1.4 零散数据 2. Stream流的中间方法 3. Stream流的终结方法 四、 练习 1. 数据过滤 2. 数据操作 - 按年龄筛选 3. 数据操作 - 演员信息要求…...

Ubuntu Protobuf 安装(测试有效)

安装流程 下载软件 下载自己要安装的版本&#xff1a;https://github.com/protocolbuffers/protobuf 下载源码编译&#xff1a; 系统环境&#xff1a;Ubuntu16&#xff08;其它版本亦可&#xff09;&#xff0c;Protobuf-3.6.1 编译源码 cd protobuf# 当使用 git clone 下来的…...

驱动程序开发:FTP服务器和OpenSSH的移植与搭建、以及一些笔记

目录一、FTP服务器移植与搭建1、在ubuntu下安装vsftpd2、在window下安装FileZilla3、移植vsftpd到开发板上4、Filezilla 连接测试5、注意点二、开发板 OpenSSH 移植与使用1、移植 zlib 库2、移植 openssl 库3、移植 openssh 库4、openssh 使用测试三、关于u-boot上的操作及根文…...

优化改进YOLOv5算法之添加GIoU、DIoU、CIoU、EIoU、Wise-IoU模块(超详细)

目录 1、IoU 1.1 什么是IOU 1.2 IOU代码 2、GIOU 2.1 为什么提出GIOU 2.2 GIoU代码 3 DIoU 3.1 为什么提出DIOU 3.2 DIOU代码 4 CIOU 4.1 为什么提出CIOU 4.2 CIOU代码 5 EIOU 5.1 为什么提出EIOU 5.2 EIOU代码 6 Wise-IoU 7 YOLOv5中添加GIoU、DIoU、CIoU、…...

windows电脑pc如何使用svn获取文档和代码

一、安装svn 下载链接 也可通过其他方式下载 二、使用 2.1 随便找一个文件夹 2.2 点击右键&#xff0c;选择SVN Checkout 2.3输入网址 如当你在网页上访问时地址为https://10.197.78.78/!/#aaa/view/head/bbb 在这里不能直接填入&#xff0c;而是 https://10.197.78.78/sv…...

ROS1学习笔记:tf坐标系广播与监听的编程实现(ubuntu20.04)

参考B站古月居ROS入门21讲&#xff1a;tf坐标系广播与监听的编程实现 基于VMware Ubuntu 20.04 Noetic版本的环境 文章目录一、创建功能包二、创建代码2.1 以C为例2.1.1 配置代码编译规则2.1.2 编译整个工作空间2.1.2 配置环境变量2.1.4 执行代码2.2 以Python为例2.2.1 配置代码…...

​力扣解法汇总1590. 使数组和能被 P 整除

目录链接&#xff1a; 力扣编程题-解法汇总_分享记录-CSDN博客 GitHub同步刷题项目&#xff1a; https://github.com/September26/java-algorithms 原题链接&#xff1a;力扣 描述&#xff1a; 给你一个正整数数组 nums&#xff0c;请你移除 最短 子数组&#xff08;可以为 …...

Spring源码阅读(基础)

第一章&#xff1a;bean的元数据 1.bean的注入方式&#xff1a; 1.1 xml文件 1.2 注解 Component&#xff08;自己写的类才能在上面加这些注解&#xff09; 1.3配置类&#xff1a; Configuration 注入第三方数据源之类 1.4 import注解 &#xff08;引用了Myselector类下…...

服务搭建篇(九) 使用GitLab+Jenkins搭建CI\CD执行环境 (上) 基础环境搭建

1.前言 每当我们程序员开发在本地完成开发之后 , 都要部署到正式环境去使用 , 在一些传统的运维体系中 , 开发与运维都是割裂的 , 开发人员不允许操作正式服务器 , 服务器只能通过运维团队来操作 , 这样可以极大的提高服务器的安全性 , 不经过安全保护的开放服务器 , 对于黑客…...

CDC 长沙站丨云原生技术研讨会:数字兴链,云化未来!

一、活动信息&#xff1a;活动主题&#xff1a;CDC 长沙站丨云原生技术研讨会活动时间&#xff1a;2023 年 3 月 14 日下午 14&#xff1a;30-17&#xff1a;30活动地点&#xff1a;长沙市岳麓区-拓维信息总部 1 楼多功能厅活动参与方式&#xff1a;免门票参与&#xff0c;戳此…...

A.特定领域知识图谱知识推理方案:知识图谱推理算法综述[二](DTransE/PairRE:基于表示学习的知识图谱链接预测算法)

推荐参考文章: A.特定领域知识图谱知识推理方案:知识图谱推理算法综述[一](基于距离的翻译模型:TransE、TransH、TransR、TransH、TransA、RotatE) A.特定领域知识图谱知识推理方案:知识图谱推理算法综述[二](DTransE/PairRE:基于表示学习的知识图谱链接预测算法) A.…...