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

Mybatis之Sqlsession、Connection和Transaction三者间的关系

前言

最近在看Mybatis的源码,搜到这篇文章Sqlsession、Connection和Transaction原理与三者间的关系,debug之后发现有不少疑惑,于是按照原文整理了一下,记录下debug中的一些困惑点。

对于我们开发来讲,不管跟任何关系型数据库打交道都无法规避这三巨头,数据库的会话-Sqlsession、连接-Connection和事务-Transaction,今天让我们一起来梳理下这三者之间的工作原理和关系。

1、首先来解析下会话Sqlsession

会话是Mybatis持久化层跟关系型数据库交互的基础,所有的查询、数据更新(包含保存、更新、删除)操作都在与数据库建立会话的基础上进行的;MyBatis中的会话是SqlSession,默认实现是DefaultSqlSession。可以通过SqlSessionFactory的openSession来获取的。
通过SqlSessionFactory获取SqlSession的代码如下:

    String resource = "mybatis-config.xml";InputStream inputStream = Resources.getResourceAsStream(resource);SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);SqlSession sqlSession = sqlSessionFactory.openSession();

打开一个会话的时序图大致流程如下:

第一步:通过new SqlSessionFactoryBuilder().build(inputStream)来构造SqlSessionFactory,参数是配置文件的输入流。
主要实现的代码块如下:

 public SqlSessionFactory build(InputStream inputStream, String environment, Properties properties) {try {XMLConfigBuilder parser = new XMLConfigBuilder(inputStream, environment, properties);return build(parser.parse());} catch (Exception e) {throw ExceptionFactory.wrapException("Error building SqlSession.", e);} finally {ErrorContext.instance().reset();try {inputStream.close();} catch (IOException e) {// Intentionally ignore. Prefer previous error.}}}public SqlSessionFactory build(Configuration config) {return new DefaultSqlSessionFactory(config);}

第二步:XMLConfigBuilder的parse方法会解析配置文件,解析的结果就是得出一个Configuration对象。其中一步就是根据配置文件中的datasource节点解析出数据源
主要实现的代码块如下:

<dataSource type="POOLED"><!--这里会替换为local-mysql.properties中的对应字段的值--><property name="driver" value="com.mysql.cj.jdbc.Driver"/><property name="url" value="jdbc:mysql://127.0.0.1:3306/test?useUnicode=true"/><property name="username" value="root"/><property name="password" value="12345678"/><property name="poolMaximumActiveConnections" value="2"/><property name="poolMaximumIdleConnections" value="2"/>
</dataSource>

第三步:SqlSessionFactory的openSession会获取SqlSession。具体实现代码如下:

    Transaction tx = null;try {final Environment environment = configuration.getEnvironment();final TransactionFactory transactionFactory = getTransactionFactoryFromEnvironment(environment);tx = transactionFactory.newTransaction(environment.getDataSource(), level, autoCommit);final Executor executor = configuration.newExecutor(tx, execType);return new DefaultSqlSession(configuration, executor, autoCommit);} catch (Exception e) {closeTransaction(tx); // may have fetched a connection so lets call close()throw ExceptionFactory.wrapException("Error opening session.  Cause: " + e, e);} finally {ErrorContext.instance().reset();}}

2、接下来再分析下Mybatis的连接Connection

MyBatis在每次执行SQL操作时,在获取Statement时,会去获取数据库连接(下面源码在SimpleExecutor)。因为每个sql的Statement不同,所以连接也不同,也就是一个Sqlsession对应多个Connection只有在开启spring事务的的前提下,当前线程才是共用一个Connection,这是因为spring在获取连接时,使用ThreadLocal在DataSource层面对Connection做了缓存(即你连接的数据源没变,Connection不变,比如没改变查询的数据库)

private Statement prepareStatement(StatementHandler handler, Log statementLog) throws SQLException {Statement stmt;Connection connection = getConnection(statementLog);stmt = handler.prepare(connection, transaction.getTimeout());handler.parameterize(stmt);return stmt;}

事务没有交spring管理

// 这里是单独运行mybatis,没和spring整合
public class MybatisHelloWorld {public static void main(String[] args) {String resource = "mybatis-config.xml";Reader reader;try {reader = Resources.getResourceAsReader(resource);SqlSessionFactory sqlMapper = new  SqlSessionFactoryBuilder().build(reader);SqlSession session = sqlMapper.openSession();try {TestAMapper mapper = session.getMapper(TestAMapper.class);TestA testA = mapper.getUser(1);mapper.getUser(2);System.out.println(testA);} finally {session.close();}} catch (IOException e) {e.printStackTrace();}}
}

查看mapper.getUser(1)和mapper.getUser(2)时,Connection获取如下图:

显然这两个Connection并不是同一个。

事务交spring管理(配置的druid数据源)

// 这里重点不是mybatis和spring的整合,相关代码省略
// 自己可以在springboot中快速导入,然后写单测走以下代码
// 也不关注回滚和提交,只关注开启事务管理后的连接获取情况即可
DefaultTransactionDefinition transactionDefinition = new DefaultTransactionDefinition();
TransactionStatus transaction = transactionManager.getTransaction(transactionDefinition);
mapper.getUser(1);
mapper.getUser(2);

 查看mapper.getUser(1)和mapper.getUser(2)时,Connection获取如下图:

显然这两个是同一个(这不是复制了一遍图啊,看handler地址就知道是两次Mapper方法的执行)。下面是获取当前线程同一数据源连接的缓存,由于不是本文重点,具体如何设置进去的就不展开了。

类似的原理在SqlSessionTemplate(功能之一就是帮我们管理SqlSession的新建和关闭,我们单独运行Mybatis是自己手动操作的,整合Spring后,直接调Mapper就行了,不用管SqlSession)也出现了,这里缓存的是当前线程的SqlSession(如果当前线程的每次执行Mapper的SqlSession不一样,那么底层Connection也会不一样,事务就没法实现了):

不好意思,以上结论是错误的!!!!设置事务手动提交:SqlSession session = sqlMapper.openSession(false);假设把mapper.getUser(1)和mapper.getUser(2)换成两个更新语句,调用session.commit()会发现提交成功。问题来了,两个更新是两个不同的connection,session.commit()底层也是调connection.commit(),一个connection不可能提交两个connection的事务啊,那么一个SqlSession就是对应一个Connection!

那么上面的debug截图明明显示不同啊,为啥呢?注意看prepareStatement方法这里生成的Connetion是带Proxy的,说明这个地方的虽然每次创建不一样的Connetion,但只是代理对象,里面其实还是一个Connetion(下图中的realConnection),如下图:

知道为啥叫realConnection了吧,这里涉及了JDK动态代理。因为代理对象的存在,导致在debug过程中,发现不同Mapper方法创建的Connection和JdbcTransaction的Connection全都不一样,如果基础比较劳,知道Connection只能提交基于它自己生成的statement执行的sql的事务,那么就不会有这个困惑了。

回到主线,我们配置的数据源为POOLED,这里会使用PooledDataSource来获取Connection。

 @Overridepublic Connection getConnection() throws SQLException {return popConnection(dataSource.getUsername(), dataSource.getPassword()).getProxyConnection();}

这里进行了数据库的连接进行了池化管理,MyBatis通过自身的数据源PooledDataSource来进行数据库连接的管理。

3、然后再来说下事务Transaction

在执行sqlSession.commit时,会去提交事务。

    UserMapperExt userMapperExt = sqlSession.getMapper(UserMapperExt.class);userMapperExt.insert(new UserDTO("houliu",23));userMapperExt.findUserListByName("zhangsan");userMapperExt.update("name" ,"wangwu",22);sqlSession.commit();

执行commit后,会调用如下代码:

一个sqlSession中可以进行多个事务提交:

    userMapperExt1.insert(new UserDTO("houliu",23));userMapperExt1.findUserListByName("zhangsan");userMapperExt1.update("name" ,"wangwu",22);sqlSession1.commit();//SqlSession sqlSession2 = sqlSessionFactory.openSession();UserMapperExt userMapperExt2 = sqlSession1.getMapper(UserMapperExt.class);userMapperExt2.insert(new UserDTO("houliu",23));userMapperExt2.findUserListByName("zhangsan");userMapperExt2.update("name" ,"wangwu",22);sqlSession1.commit();

原生jdbc中一个connection可以执行多次commit:

Class.forName(“com.mysql.cj.jdbc.Driver”); //classLoader,加载对应驱动
Connection connection = DriverManager.getConnection(“jdbc:mysql://127.0.0.1:3306/test?useUnicode=true”, “root”, “12345678”);
connection.setAutoCommit(false);
PreparedStatement preparedStatement = connection.prepareStatement(“update cnt_user set age = 201 where name = ‘zhangsan’”);
preparedStatement.execute();connection.commit();preparedStatement = connection.prepareStatement("update cnt_user set age = 233 where name = 'zhangsan'");
preparedStatement.execute();
preparedStatement = connection.prepareStatement("insert into cnt_user (age , name) values(100 ,'liusi')");
preparedStatement.execute();connection.commit();

可以看出,事务是依附在SqlSession上的。好了,讲完了上面三者的原理后,最后我们来总结下三者的关系。

Sqlsession、Connection和Transaction之间关系

连接可以通过数据库连接池被复用。在MyBatis中,不同时刻的SqlSession可以复用同一个Connection,同一个SqlSession中可以提交多个事务。事务回滚与提交其实都是调Connection的相关方法,即同一个事务内,sql操作使用同一个数据库连接。因此,连接—会话—事务的关系如下:

  • Connection与SqlSession一 一对应(Connection一对多SqlSession是SqlSession关闭了情况下又新建一个SqlSession,即上面说的所谓不同时刻,因为连接池的存在,不可能多个SqlSession同时对应同一个连接,所以只能算一 一对应)。
  • Connection与SqlSession两者与Transaction是一对多。

从经典的JDBC操作数据库的几个步骤出发再看Mybatis的源码,就能明白,SqlSession是对Connection的高级封装,它作为Mybatis的接口层,提供了一系列增删改查接口,我们通过它可以直接操作数据库,而原生的Connection,我们还得创建PreparedStatement,预处理sql,处理返回结果等等,而这些操作,SqlSession接口底层已经为我们实现了。

相关文章:

Mybatis之Sqlsession、Connection和Transaction三者间的关系

前言 最近在看Mybatis的源码&#xff0c;搜到这篇文章Sqlsession、Connection和Transaction原理与三者间的关系&#xff0c;debug之后发现有不少疑惑&#xff0c;于是按照原文整理了一下&#xff0c;记录下debug中的一些困惑点。 对于我们开发来讲&#xff0c;不管跟任何关系…...

WRT1900ACS搭建openwrt服务器小记

参考链接 wrt1900acs openwrt wrt1900acs openwrt 刷机 wrt1900acs原生固件刷openwrt-23.05.3-mvebu-cortexa9-linksys_wrt1900acs-squashfs-factory.img wrt1900acs openwrt更新刷openwrt-23.05.3-mvebu-cortexa9-linksys_wrt1900acs-squashfs-sysupgrade.bin 通过WEB UI来…...

Spring AOP(3)

目录 Spring AOP原理 代理模式 代理模式中的主要角色 静态代理 动态代理 总结:面试题 什么是AOP? Spring AOP实现的方式有哪些? Spring AOP实现原理 Spring使用的是哪种代理方式? JDK和CGLIB动态代理的区别? Spring AOP原理 代理模式 代理模式, 也叫委托模式. …...

推荐5个免费的国内平替版GPT

提起AI&#xff0c;大家第一个想到的就是GPT。 虽然它确实很厉害&#xff0c;但奈何于我们水土不服&#xff0c;使用门槛有些高。 不过随着GPT的爆火&#xff0c;现在AI智能工具已经遍布到各行各业了&#xff0c;随着时间的推移&#xff0c;国内的AI工具也已经“百花盛放”了…...

弹性云服务器是什么,为何如此受欢迎

云计算作为当下炙手可热的技术领域&#xff0c;已然成为现代企业不可或缺的核心能力。云服务器作为云计算的基石之一&#xff0c;在这个数字化时代发挥着至关重要的作用。而弹性云服务器&#xff0c;作为云服务器的一种演进形式&#xff0c;更是备受瞩目。 弹性云服务器&#…...

Docker部署RabbitMQ与简单使用

官网地址&#xff1a; Messaging that just works — RabbitMQ 我的Docker博客:Docker-CSDN博客 1.结构 其中包含几个概念&#xff1a; **publisher**&#xff1a;生产者&#xff0c;也就是发送消息的一方 **consumer**&#xff1a;消费者&#xff0c;也就是消费消息的一方 …...

2024年黄石市建设优质工程评价认定申报条件、流程及材料合集

2024年黄石市建设优质工程评价认定申报条件、流程及材料合集如下&#xff0c;黄石市的企业单位可以了解一下&#xff0c;有疑问名字找我哦。 第一章总则 第一条为贯彻落实《中华人民共和国建筑法》、《安全生产法》、《建设工程质量管理条例》、《建设工程安全生产管理条例》…...

偏微分方程算法之混合边界条件下的差分法

目录 一、研究目标 二、理论推导 三、算例实现 四、结论 一、研究目标 我们在前几节中介绍了Poisson方程的边值问题&#xff0c;接下来对椭圆型偏微分方程的混合边值问题进行探讨&#xff0c;研究对象为&#xff1a; 其中&#xff0c;为矩形区域&#xff0c;为上的连续函数…...

apollo资料整理

Application X: Application X Apollo: Apollo 自动驾驶开放平台 Cyber RT API tutorial — Cyber RT Documents documentation Cyber RT API tutorial — Cyber RT Documents documentation GitHub - daohu527/dig-into-apollo: Apollo notes (Apollo学习笔记) - Apollo l…...

森林消防新利器:高扬程水泵的革新与应用/恒峰智慧科技

随着全球气候变化的加剧&#xff0c;森林火灾的频发已成为威胁生态安全的重要问题。在森林消防工作中&#xff0c;高效、快速的水源供给设备显得尤为重要。近年来&#xff0c;高扬程水泵的广泛应用&#xff0c;为森林消防工作带来了新的希望与突破。 一、高扬程水泵的技术优势 …...

Microsoft Universal Print 与 SAP 集成教程

引言 从 SAP 环境打印是许多客户的要求。例如数据列表打印、批量打印或标签打印。此类生产和批量打印方案通常使用专用硬件、驱动程序和打印解决方案来解决。 Microsoft Universal Print 是一种基于云的打印解决方案&#xff0c;它允许组织以集中化的方式管理打印机和打印机驱…...

VBA在Excel中字母、数字的相互转化

VBA在Excel中字母、数字的相互转化 字母转数字的方法 数字转字母的方法 众所周知,Excel表中的行以数字展示,列用字母展示,如下图: 编程时,很多时候需要将列的字母转变为数字使用,如cells(num1,num2).value等,不知大家是怎么将字母转化为数字的,Excel是否有其他方式…...

【C语言】——联合体与枚举

【C语言】——联合体与枚举 一、联合体1.1、联合体类型的声明1.2、联合体的特点1.3、相同成员的结构体和联合体对比1.4、联合体的大小计算1.5、联合体的应用举例 二、枚举2.1、枚举类型的声明2.2、枚举类型的优点 一、联合体 1.1、联合体类型的声明 联合体也叫做共用体   与…...

java线上问题排查之内存分析(三)

java线上问题排查之内存分析 使用top命令 top命令显示的结果列表中&#xff0c;会看到%MEM这一列&#xff0c;这里可以看到你的进程可能对内存的使用率特别高。以查看正在运行的进程和系统负载信息&#xff0c;包括cpu负载、内存使用、各个进程所占系统资源等。 2.用jstat命令…...

中电金信:金Gien乐道 | 4月要闻速览,精彩再回顾

中国电子党组副书记、总经理李立功一行调研中电金信 4月10日&#xff0c;中国电子党组副书记、总经理李立功一行赴中电金信进行调研&#xff0c;深入听取了中电金信经营发展情况、研发工作及“源启”行业数字底座平台的汇报&#xff0c;并参观了公司展厅和科技研发场所&#xf…...

Java将文件目录转成树结构

在实际开发中经常会遇到返回树形结构的场景&#xff0c;特别是在处理文件系统或者是文件管理系统中。下面就介绍一下怎么将文件路径转成需要的树形结构。 在Java中&#xff0c;将List<String>转换成树状结构&#xff0c;需要定义一个树节点类&#xff08;TreeNode&#…...

硬件工程师必读:10条职业发展黄金法则!

在快速发展的科技时代&#xff0c;硬件工程师作为推动技术创新和产业升级的重要力量&#xff0c;其职业发展之路既充满挑战也蕴含无限机遇。为了在这条道路上稳步前行&#xff0c;我们首先需要了解硬件产品的研发流程。 在这个过程中&#xff0c;公司内的每个岗位都发挥着不可或…...

Redis是什么? 日常运维 Redis 需要注意什么 ? 怎么降低Redis 内存使用 节省内存?

你的项目或许已经使用 Redis 很长时间了&#xff0c;但在使用过程中&#xff0c;你可能还会或多或少地遇到以下问题&#xff1a; 我的 Redis 内存为什么增长这么快&#xff1f;为什么我的 Redis 操作延迟变大了&#xff1f;如何降低 Redis 故障发生的频率&#xff1f;日常运维…...

【Android项目】“追茶到底”项目介绍

没有多的介绍&#xff0c;这里只是展示我的项目效果&#xff0c;后面会给出具体的代码实现。 一、用户模块 1、注册&#xff08;第一次登陆的话需要先注册账号&#xff09; 2、登陆&#xff08;具有记住最近登录用户功能&#xff09; 二、点单模块 1、展示饮品列表 2、双向联动…...

机试:进制转换问题

十进制转任意进制 简单回忆一下十进制我们是怎么转换成二进制的&#xff08;短除法&#xff09;&#xff1a; 我们会将十进制数不断的进行除2操作&#xff0c;并且记录下每一次的余数&#xff08;这个余数就是我们最终求的二进制数的组成部分&#xff09;。 以下以12D举例&a…...

目标检测实战(十五): 使用YOLOv7完成对图像的目标检测任务(从数据准备到训练测试部署的完整流程)

文章目录 一、目标检测介绍二、YOLOv7介绍三、源码/论文获取四、环境搭建4.1 环境检测 五、数据集准备六、 模型训练七、模型验证八、模型测试九、错误总结9.1 错误1-numpy jas mp attribute int9.2 错误2-测试代码未能跑出检测框9.3 错误3- Command git tag returned non-zero…...

github中fasttext库README官文文档翻译

参考链接&#xff1a;fastText/python/README.md at main facebookresearch/fastText (github.com) fastText模块介绍 fastText 是一个用于高效学习单词表述和句子分类的库。在本文档中&#xff0c;我们将介绍如何在 python 中使用 fastText。 环境要求 fastText 可在现代 …...

WouoUIPagePC端实现

WouoUIPagePC端实现 WouoUIPage是一个与硬件平台无关&#xff0c;纯C语言的UI库&#xff08;目前只能应用于128*64的单色OLED屏幕上&#xff0c;后期会改进&#xff0c;支持更多尺寸&#xff09;。因此&#xff0c;我们可以在PC上实现它&#xff0c;本文就以在PC上使用 VScode…...

W801学习笔记十九:古诗学习应用——下

经过前两章的内容&#xff0c;背唐诗的功能基本可以使用了。然而&#xff0c;仅有一种模式未免显得过于单一。因此&#xff0c;在本章中对其进行扩展&#xff0c;增加几种不同的玩法&#xff0c;并且这几种玩法将采用完全不同的判断方式。 玩法一&#xff1a;三分钟限时挑战—…...

类加载器ClassLoad-jdk1.8

类加载器ClassLoad-jdk1.8 1. 类加载器的作用2. 类加载器的种类&#xff08;JDK8&#xff09;3. jvm内置类加载器如何搜索加载类--双亲委派模型4. 如何打破双亲委派模型--自定义类加载器5. 自定义一个类加载器5.1 为什么需要自定义类加载器5.2 自定义一个类加载器 6. java代码加…...

24年最新AI数字人简单混剪

24年最新AI数字人简单混剪 网盘自动获取 链接&#xff1a;https://pan.baidu.com/s/1lpzKPim76qettahxvxtjaQ?pwd0b8x 提取码&#xff1a;0b8x...

免备案香港主机会影响网站收录?

免备案香港主机会影响网站收录?前几天遇到一个做电子商务的朋友说到这个使用免备案香港主机的完整会不会影响网站的收录问题&#xff0c;这个问题也是站长关注较多的问题之一。小编查阅了百度官方规则说明&#xff0c;应该属于比较全面的。下面小编给大家介绍一下使用免备案香…...

低代码工业组态数字孪生平台

2024 两会热词「新质生产力」凭借其主要特征——高科技、高效能及高质量&#xff0c;引发各界关注。在探索构建新质生产力的重要议题中&#xff0c;数据要素被视为土地、劳动力、资本和技术之后的第五大生产要素。数据要素赋能新质生产力发展主要体现为&#xff1a;生产力由生产…...

代码随想录第三十八天(完全背包问题)|爬楼梯(第八期模拟笔试)|零钱兑换|完全平方数

爬楼梯&#xff08;第八期模拟笔试&#xff09; 该题也是昨天的完全背包排列问题&#xff0c;解法相同&#xff0c;将遍历顺序进行调换 import java.util.*; public class Main{public static void main (String[] args) {Scanner scnew Scanner(System.in);int nsc.nextInt(…...

idea常用知识点随记

idea常用知识点随记 1. 打开idea隐藏的commit窗口2. idea中拉取Git分支代码3. idea提示代码报错&#xff0c;项目编译没有报错4. idea中实体类自动生成序列号5. idea隐藏当前分支未commit代码6. idea拉取新建分支的方法 1. 打开idea隐藏的commit窗口 idea左上角File→Settings…...

(双指针) 有效三角形的个数 和为s的两个数字 三数之和 四数之和

提示&#xff1a;文章写完后&#xff0c;目录可以自动生成&#xff0c;如何生成可参考右边的帮助文档 目录 文章目录 前言 一、有效三角形的个数&#xff08;medium&#xff09; 1.1、题目 1.2、讲解算法原理 1.3、编写代码 二、和为s的两个数字 2.1、题目 2.2、讲解算…...

力扣每日一题114:二叉树展开为链表

题目 中等 提示 给你二叉树的根结点 root &#xff0c;请你将它展开为一个单链表&#xff1a; 展开后的单链表应该同样使用 TreeNode &#xff0c;其中 right 子指针指向链表中下一个结点&#xff0c;而左子指针始终为 null 。展开后的单链表应该与二叉树 先序遍历 顺序相同…...

Linux系统下使用LVM扩展逻辑卷的步骤指南

Linux系统下使用LVM扩展逻辑卷的步骤指南 文章目录 Linux系统下使用LVM扩展逻辑卷的步骤指南前言一、逻辑卷管理&#xff08;LVM&#xff09;简介二、扩展逻辑卷步骤1. 检查当前的磁盘布局2. 创建新的分区3. 更新内核的分区表4. 初始化新的物理卷5. 将物理卷添加到卷组6. 调整逻…...

探索AI编程新纪元:从零开始的智能编程之旅

提示&#xff1a;Baidu Comate 智能编码助手是基于文心大模型&#xff0c;打造的新一代编码辅助工具 文章目录 前言AI编程概述&#xff1a;未来已来场景需求&#xff1a;从简单到复杂&#xff0c;无所不包体验步骤&#xff1a;我的AI编程初探试用感受&#xff1a;双刃剑下的深思…...

RustGUI学习(iced)之小部件(三):如何使用下拉列表pick_list?

前言 本专栏是学习Rust的GUI库iced的合集,将介绍iced涉及的各个小部件分别介绍,最后会汇总为一个总的程序。 iced是RustGUI中比较强大的一个,目前处于发展中(即版本可能会改变),本专栏基于版本0.12.1. 概述 这是本专栏的第三篇,主要讲述下拉列表pick_list部件的使用,会…...

【OceanBase诊断调优】—— Unit 迁移问题的排查方法

适用版本&#xff1a;V2.1.x、V2.2.x、V3.1.x、V3.2.x 本文主要介绍 OceanBase 数据集在副本迁移过程中遇到的问题的排查方法。 适用版本 V2.1.x、V2.2.x、V3.1.x、V3.2.x 手动调度迁移问题的排查 OceanBase 数据库的 RootService 模块负责 Unit 迁移的调度&#xff0c;如果…...

[极客大挑战 2019]PHP

1.通过目录扫描找到它的备份文件&#xff0c;这里的备份文件是它的源码。 2.源码当中涉及到的关键点就是魔术函数以及序列化与反序列化。 我们提交的select参数会被进行反序列化&#xff0c;我们要构造符合输出flag条件的序列化数据。 但是&#xff0c;这里要注意的就是我们提…...

数据结构之跳跃表

跳跃表 跳跃表&#xff08;skiplist&#xff09;是一种随机化的数据&#xff0c; 由 William Pugh 在论文《Skip lists: a probabilistic alternative to balanced trees》中提出&#xff0c; 跳跃表以有序的方式在层次化的链表中保存元素&#xff0c; 效率和平衡树媲美 —— …...

搜维尔科技:动作捕捉解决方案:销售、服务、培训和支持

动作捕捉解决方案&#xff1a;销售、服务、培训和支持 搜维尔科技&#xff1a;动作捕捉解决方案&#xff1a;销售、服务、培训和支持l...

数据库管理-第184期 23ai:干掉MongoDB的不一定是另一个JSON数据库(20240507)

数据库管理184期 2024-05-07 数据库管理-第184期 23ai:干掉MongoDB的不一定是另一个JSON数据库&#xff08;20240507&#xff09;1 JSON需求2 关系型表设计3 JSON关系型二元性视图3 查询视图总结 数据库管理-第184期 23ai:干掉MongoDB的不一定是另一个JSON数据库&#xff08;20…...

刷代码随想录有感(58):二叉树的最近公共祖先

题干&#xff1a; 代码&#xff1a; class Solution { public:TreeNode* traversal(TreeNode* root, TreeNode* p, TreeNode* q){if(root NULL)return NULL;if(root p || root q)return root;TreeNode* left traversal(root->left, p, q);TreeNode* right traversal(r…...

[开发|安卓] Android Studio 开发环境配置

Android Studio下载 Android Studio下载地址 下载SDK依赖 1.点击左上角菜单 2.选择工具 3.打开SDK管理中心 4.下载项目目标Android版本的SDK 配置安卓虚拟机 1.打开右上角的设备管理 2.选择合适的手机规格 3.下载并选择项目目标Android系统 4.点击完成配置 …...

开发 Chrome 浏览器插件入门

目录 前言 一&#xff0c;创建插件 1.创建一个新的目录 2.编写清单文件 二&#xff0c;高级清单文件 1.编写放置右窗口 2.常驻的后台JS或后台页面 3.event-pages 短周期使用 三&#xff0c;Chrome 扩展 API 函数 1.浏览器操作函数 2.内容脚本函数 3.后台脚本函数 4…...

在数字化转型的浪潮中,CBDB百数服务商如何破浪前行?

在信息化时代&#xff0c;传统咨询企业面临着数字化转型的挑战与机遇。如何利用数字化技术提升业务效率、增强客户黏性&#xff0c;成为了行业关注的焦点。云南析比迪彼企业管理有限公司&#xff08;CBDB&#xff09;作为云南地区的企业咨询服务提供商&#xff0c;率先与百数展…...

程序员的实用神器

在软件开发的海洋中&#xff0c;程序员的实用神器如同航海中的指南针&#xff0c;帮助他们导航、加速开发、优化代码质量&#xff0c;并最终抵达成功的彼岸。这些工具覆盖了从代码编写、版本控制到测试和部署的各个环节。然而&#xff0c;程序员们通常会有一套自己喜欢的工具集…...

spss 导入数据的时候 用于确定数据类型的值所在的百分比95%是什么意思,数据分析,医学数据分析

在SPSS中&#xff0c;当提及“数据类型的值所在的百分比95%”时&#xff0c;这通常与数据的统计分布或置信区间有关&#xff0c;而不是直接关于数据类型的定义。 导入数据的时候需要定义数据类型&#xff0c;那么根据提供的数据&#xff0c;来定义&#xff0c;有时候&#xff…...

Python进阶之-上下文管理器

✨前言&#xff1a; &#x1f31f;什么是上下文管理器&#xff1f; 在Python中&#xff0c;上下文管理器是支持with语句的对象&#xff0c;用于为代码块提供设置及清理代码。上下文管理器广泛应用于资源管理场景&#xff0c;例如文件操作、网络连接、数据库会话等&#xff0c…...

什么年代了,还在拿考勤说事

最近&#xff0c;看到了某公司的一项考勤规定&#xff1a;自然月内&#xff0c;事假累计超过3次或者累计请假时间超过8小时的&#xff0c;不予审批&#xff0c;强制休假的按旷工处理。 真的想吐槽&#xff0c;什么年代了&#xff0c;还在拿考勤说事&#xff0c;这是什么公司、什…...

泰迪智能科技中职大数据实验室建设(职业院校大数据实验室建设指南)

职校大数据实验室是职校校园文化建设的重要部分&#xff0c;大数据实训室的建设方案应涵盖多个方面&#xff0c;包括硬件设施的配备、软件环境的搭建、课程资源的开发、师资力量的培养以及实践教学体系的完善等。 打造特色&#xff0c;对接生产 社会经济与产业的…...

Qt QThreadPool线程池

1.简介 QThreadPool类管理一个QThread集合。 QThreadPool管理和重新设计单个QThread对象&#xff0c;以帮助降低使用线程的程序中的线程创建成本。每个Qt应用程序都有一个全局QThreadPool对象&#xff0c;可以通过调用globalInstance来访问该对象。 要使用其中一个QThreadPool…...

普通人也能创业!轻资产短视频带货项目,引领普通人实现创业梦想

在这个信息爆炸的时代&#xff0c;创业似乎成为了越来越多人的梦想。然而&#xff0c;传统的创业模式 keJ0277 往往伴随着高昂的资金投入和复杂的管理流程&#xff0c;让许多普通人望而却步。然而&#xff0c;现在有一种轻资产短视频带货项目正在悄然兴起&#xff0c;它以其低…...

前端面试题(三)答案版

面试形式&#xff1a;线上面试&#xff08;不露脸&#xff1a;腾讯会议&#xff09;&#xff1a;时长30分钟 面试评价&#xff1a;面试官给的题目宽泛&#xff0c;面试者灵活作答 面试官&#xff1a;技术人员 面试官的提问大纲&#xff1a;我们自身简历本公司招聘要求 面试…...

CV每日论文--2024.5.15

1、Can Better Text Semantics in Prompt Tuning Improve VLM Generalization? 中文标题&#xff1a;更好的文本语义在提示微调中能否提高视觉语言模型的泛化能力? 简介&#xff1a;这篇论文介绍了一种新的可学习提示调整方法,该方法超越了仅对视觉语言模型进行微调的传统方…...

WordPress建站公司模板免费下载

WordPress建站公司 适合提供WordPress建站服务的公司或个体(个人)工作室使用的WordPress建站公司主题模板。 演示 https://www.jianzhanpress.com/?p545 https://www.wpicu.com/jianzhan/ 下载 链接: https://pan.baidu.com/s/11trlwUJq_lW81R_acq4ilA 提取码: r19i...

【Python】图像批量合成视频,并以文件夹名称命名合成的视频

一个文件夹中有多个子文件夹&#xff0c;子文件夹中有多张图像。如何把批量把子文件夹中的图像合成视频&#xff0c;视频名称是子文件夹的名称&#xff0c;生成的视频保存到指定文件夹&#xff0c;效果记录。 代码 import os import cv2def create_video_from_images(image_f…...

pytorch_trick(2) 在Jupyter初始化过程中自动加载常用包的设置方法

一、在Jupyter初始化过程中自动加载常用包的设置方法 在每一节课程的开头&#xff0c;我们都要导入常用包&#xff0c;由于这项工作重复而固定&#xff0c;因此我们也可以通过配置jupyter&#xff08;准确来说应该是ipython&#xff09;的startup文件&#xff0c;来使得每次新创…...