Spring声明式事务以及事务传播行为
Spring声明式事务以及事务传播行为
- Spring声明式事务
- 1.编程式事务
- 2.使用AOP改造编程式事务
- 3.Spring声明式事务
- 事务传播行为
如果对数据库事务不太熟悉,可以阅读上一篇博客简单回顾一下:
MySQL事务以及并发访问隔离级别
Spring声明式事务
-
事务一般添加到JavaEE三层结构中的service层(业务逻辑层)
-
在Spring进行事务管理操作的两种方式
-
编程式事务管理
-
声明式事务管理
-
**转账案例代码准备:**按照以下代码配置完成之后可以进行数据库的操作,但不涉及事务。
-
数据库
create database spring_db; use spring_db; create table account(id int primary key auto_increment,name varchar(20),money double ); insert into account values(null,'jack',1000),(null,'rose',1000);
-
导入Maven依赖
<dependencies><!--Spring核心包--><dependency><groupId>org.springframework</groupId><artifactId>spring-context</artifactId><version>5.2.10.RELEASE</version></dependency><!-- 切入点表达式 --><dependency><groupId>org.aspectj</groupId><artifactId>aspectjweaver</artifactId><version>1.9.4</version></dependency><!--mybatis的包--><dependency><groupId>org.mybatis</groupId><artifactId>mybatis</artifactId><version>3.5.6</version></dependency><!--Druid数据库连接池--><dependency><groupId>com.alibaba</groupId><artifactId>druid</artifactId><version>1.1.16</version></dependency><!--数据库驱动包,我的MySQL版本是8.0.33--><dependency><groupId>mysql</groupId><artifactId>mysql-connector-java</artifactId><version>8.0.33</version></dependency><!--spring整合mybatis,需要下面两个jar包--><dependency><groupId>org.springframework</groupId><artifactId>spring-jdbc</artifactId><version>5.2.10.RELEASE</version></dependency><dependency><groupId>org.mybatis</groupId><artifactId>mybatis-spring</artifactId><version>1.3.0</version></dependency><!-- 引入单元测试的jar包(需要在 4.12以上) --><dependency><groupId>junit</groupId><artifactId>junit</artifactId><version>4.13.2</version></dependency><!-- Spring整合junit的jar包 --><dependency><groupId>org.springframework</groupId><artifactId>spring-test</artifactId><version>5.2.10.RELEASE</version></dependency> </dependencies>
-
jdbc.properties配置文件
jdbc.driver=com.mysql.cj.jdbc.Driver jdbc.url=jdbc:mysql://localhost:3306/spring_db jdbc.username=root jdbc.password=123456
-
MyBatisConfig配置类
public class MyBatisConfig {@Beanpublic SqlSessionFactoryBean getSqlSessionFactoryBean(DataSource ds){SqlSessionFactoryBean factoryBean = new SqlSessionFactoryBean();//设置pojo的包扫描factoryBean.setTypeAliasesPackage("top.codermao.domain");//设置连接池factoryBean.setDataSource(ds);return factoryBean;}@Beanpublic MapperScannerConfigurer mapperScannerConfigurer(){MapperScannerConfigurer msc = new MapperScannerConfigurer();//设置dao层的接口扫描msc.setBasePackage("top.codermao.dao");return msc;} }
-
Spring配置类
@Configuration @ComponentScan("top.codermao") @PropertySource("classpath:jdbc.properties") @Import(MyBatisConfig.class) public class SpringConfig {@Value("${jdbc.driver}")private String driver;@Value("${jdbc.url}")private String url;@Value("${jdbc.username}")private String username;@Value("${jdbc.password}")private String password;@Beanpublic DataSource getDataSource(){DruidDataSource ds = new DruidDataSource();ds.setDriverClassName(driver);ds.setUrl(url);ds.setUsername(username);ds.setPassword(password);return ds;}}
-
dao层接口
public interface AccountDao {//转出@Update("update account set money = money - #{money} where id = #{outId}")int outMoney(@Param("outId") int outId, @Param("money")double money);//转入@Update("update account set money = money + #{money} where id = #{inId}")int inMoney(@Param("inId") int inId, @Param("money")double money); }
-
domain包下实体类
public class Account implements Serializable {private Integer id;private String name;private Double money;public Integer getId() {return id;}public void setId(Integer id) {this.id = id;}public String getName() {return name;}public void setName(String name) {this.name = name;}public Double getMoney() {return money;}public void setMoney(Double money) {this.money = money;}@Overridepublic String toString() {return "Account{" +"id=" + id +", name='" + name + '\'' +", money=" + money +'}';}}
-
service层接口
public interface AccountService {//转账业务void transfer(int outId,int inId,double money); }
-
service层实现类
@Service public class AccountServiceImpl implements AccountService {@Autowiredprivate AccountDao dao;@Overridepublic void transfer(int outId, int inId, double money) {try {dao.outMoney(outId, money);//可能在转账过程中发生意外: 转出执行,转入还未执行 // int i = 1/0;dao.inMoney(inId, money);} catch (Exception e) {e.printStackTrace();}} }
-
WebApp类充当Controller层,负责数据的发送和接收
@RunWith(SpringJUnit4ClassRunner.class) @ContextConfiguration(classes = SpringConfig.class) public class WebApp {@Autowiredprivate AccountService service;@Testpublic void test01(){service.transfer(1, 2, 200);} }
1.编程式事务
在学习声明式事务之前我们需要了解编程式事务,因为声明式事务是Spring对编程式事务的封装。
- 所谓编程式事务是指用Spring中事务相关的API用硬编码方式来实现事务
- 缺点
- 事务管理代码和业务代码耦合严重
- 后续添加其他业务方法还要重新编写事务代码,冗余
- 缺点
所以学习编程式事务,就是学习Spring事务管理相关API。
步骤一:创建事务管理器
# PlatformTransactionManager(平台事务管理器)
1. 这是一个接口,以下是实现类1). - DataSourceTransactionManager (重点!!!)适用于Spring JDBC或MyBatis2). - HibernateTransactionManager 适用于Hibernate3.0及以上版本 3). - JpaTransactionManager适用于JPA (Java EE 标准之一,为POJO提供持久化标准规范,并规范了持久化开发的统一API,符合JPA规范的开发可以在不同的JPA框架下运行)
2. 此接口定义了事务的基本操作 1). 获取事务 :TransactionStatus getTransaction(TransactionDefinition definition)2). 提交事务 :void commit(TransactionStatus status) 3). 回滚事务 :void rollback(TransactionStatus status)
步骤二:定义事务属性TransactionDefinition
# TransactionDefinition(定义事务属性)
1. 实现类DefaultTransactionDefinition
2. 此接口定义了事务的基本信息
//2. 创建事务定义对象
DefaultTransactionDefinition td = new DefaultTransactionDefinition();
/*设置事务隔离级别0). spring默认隔离级别是跟数据库软件一致1). mysql默认是REPEATABLE_READ2). oracle默认是READ_COMMITTED*/
td.setIsolationLevel(TransactionDefinition.ISOLATION_DEFAULT);
/*设置是否只读1). false,表示读写均可(默认设置,适合增删改操作)2). true,表示只读(适合查,效率高)
*/
td.setReadOnly(false);
/*设置超时时间1). 默认值是-1, 表示永不超时2). 单位是秒
*/
td.setTimeout(10);
/*设置事务传播行为1. 一般增删改:REQUIRED (默认值)2. 一般查询 SUPPORTS
*/
td.setPropagationBehavior(TransactionDefinition.PROPAGATION_REQUIRED);
步骤三:开启事务
# TransactionStatus(接口)
`public final TransactionStatus getTransaction(@Nullable TransactionDefinition definition) throws TransactionException`
调用事务管理器的getTransaction方法,即可开启一个事务
这个方法会返回一个TransactionStatus表示事务状态的一个对象,通过TransactionStatus提供的一些方法可以用来控制事务的一些状态,比如事务最终是需要回滚还是需要提交。- 获取事务是否处于新开启事务状态- boolean isNewTransaction()
- 获取事务是否处于已完成状态- boolean isCompleted()
- 获取事务是否处于回滚状态- boolean isRollbackOnly()
- 刷新事务状态- void flush()
- 获取事务是否具有回滚存储点- boolean hasSavepoint()
- 设置事务处于回滚状态- void setRollbackOnly()
步骤四:执行业务操作
- 书写业务逻辑代码
步骤五:提交 or 回滚
-
无异常发生,提交
dstm.commit(ts);
-
有异常发生,回滚
dstm.rollback(ts);
对service层AccountServiceImpl的transfer方法添加编程式事务
@Service
public class AccountServiceImpl implements AccountService {@Autowiredprivate AccountDao dao;@Autowiredprivate DataSource dataSource;@Overridepublic void transfer(int outId, int inId, double money) {//1.创建事务管理器DataSourceTransactionManager dstm = new DataSourceTransactionManager();//为事务管理器添加与数据层相同的数据源dstm.setDataSource(dataSource);//2.创建事务定义对象,设置隔离级别、传播特性、超时时间...DefaultTransactionDefinition td = new DefaultTransactionDefinition();/*设置事务隔离级别0). spring默认隔离级别是跟数据库软件一致 (ISOLATION_DEFAULT)1). mysql默认是REPEATABLE_READ2). oracle默认是READ_COMMITTED*/td.setIsolationLevel(TransactionDefinition.ISOLATION_DEFAULT);/*设置是否为只读事务1). false,表示读写均可(默认设置,适合增删改操作)2). true,表示只读(适合查,效率高)*/td.setReadOnly(false);/*设置超时时间1). 默认值是-1, 表示永不超时2). 单位是秒*/td.setTimeout(10);/*设置事务传播行为1. 一般增删改:REQUIRED (默认值)2. 一般查询 SUPPORTS*/td.setPropagationBehavior(TransactionDefinition.PROPAGATION_REQUIRED);//3.创建事务状态对象,用于控制事务执行(了解) -> 相当于开启事务TransactionStatus ts = dstm.getTransaction(td);try {dao.outMoney(outId, money);//可能在转账过程中发生意外: 转出执行,转入还未执行
// int i = 10/0;dao.inMoney(inId, money);dstm.commit(ts);//成功,提交} catch (Exception e) {e.printStackTrace();dstm.rollback(ts);//失败,回滚}}
}
2.使用AOP改造编程式事务
硬编码方式添加事务耦合度比较高,AOP面向切面编程是动态增强方法,如果引入AOP则可以将业务代码和事务代码分开,实现解耦。
使用AOP处理编程式事务解决了耦合问题。。但是还是有些不够完美。。AOP处理不具备
特例性
,任何业务添加事务都是一样的操作,对某些事务可能对事务属性有一些独特的设置。
步骤一:在SpringConfig上添加开启AOP的注解
...
@EnableAspectJAutoProxy
public class SpringConfig {...
}
步骤二:AccountServiceImpl中transfer中只需要书写业务代码
- 注意:注意: 在aop使用中,切入点方法transfer千万不能自己catch异常
@Service
public class AccountServiceImpl implements AccountService {/*注意: 在aop使用中,切入点方法千万不能自己catch异常原因: 如果切入点自己catch了异常,那么通知中是调用切入点的地方是不会感知到异常,就不会执行catch了(相当于异常通知失效)解决方案:A方案: 有异常直接抛出,不要catchB方案: 可以catch,但是再new一个异常抛出*/@Overridepublic void transfer(int outId, int inId, double money) {dao.outMoney(outId, money);//可能在转账过程中发生意外: 转出执行,转入还未执行//int i = 1/0;dao.inMoney(inId, money);}
}
步骤三:添加TxAdvice
- 将编程式事务中对事务操作的代码抽取到TxAdvice切面类中
package top.codermao.aspect;import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Pointcut;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jdbc.datasource.DataSourceTransactionManager;
import org.springframework.transaction.TransactionDefinition;
import org.springframework.transaction.TransactionStatus;
import org.springframework.transaction.support.DefaultTransactionDefinition;import javax.sql.DataSource;@Component
@Aspect
public class TxAdvice {@Autowiredprivate DataSource dataSource;@Pointcut("execution(* top.codermao.service.*Service.transfer(..))")public void pt(){}@Around("pt()")public Object around(ProceedingJoinPoint pjp){Object result = null;//1. 创建事务管理器DataSourceTransactionManager dstm = new DataSourceTransactionManager();//为事务管理器设置与数据层相同的数据源!!!dstm.setDataSource(dataSource);//2. 创建事务定义对象 : 隔离级别/传播特性/超时时间...DefaultTransactionDefinition td = new DefaultTransactionDefinition();td.setIsolationLevel(TransactionDefinition.ISOLATION_READ_COMMITTED);td.setReadOnly(false);td.setTimeout(10);td.setPropagationBehavior(TransactionDefinition.PROPAGATION_REQUIRED);//3.创建事务状态对象,用于控制事务执行(了解) -> 相当于开启事务TransactionStatus ts = dstm.getTransaction(td);try{result = pjp.proceed();dstm.commit(ts);//成功,提交} catch (Throwable e) {e.printStackTrace();dstm.rollback(ts);//失败,回滚System.out.println("aop改造编程式事务");}return result;}
}
3.Spring声明式事务
spring底层封装了事务切面类TxAdvice, 让开发者声明配置即可用
步骤一:在SpringConfig类上添加注解开启Spring事务管理支持
...
@EnableTransactionManagement
public class SpringConfig {...
}
步骤二:在SpringConfig类中配置事务管理器
...
@EnableTransactionManagement
public class SpringConfig {...@Beanpublic DataSourceTransactionManager getTxManager(DataSource dataSource){//这里使用DataSourceTransactionManager,因为使用的是MyBatisDataSourceTransactionManager manager = new DataSourceTransactionManager();manager.setDataSource(dataSource);return manager;}
}
步骤三:在需要添加事务的方法上添加@Transactional注解
使其成为切入点
-
@Transactional注解属性
- 属性都有默认值
-
@Transactional放置位置不同,效果不同
- 如果放在类的方法上,说明当前方法是切入点
- 如果放在类上,说明当前类的所有方法是切入点
- 如果放在接口的方法上,说明此方法的所有重写方法是切入点 (常用)
- 如果放在接口上,说明此接口的所有实现类的所有方法都是切入点 (常用)
事务传播行为
事务传播行为:指的就是当一个事务方法B被另一个事务方法A调用时,这个事务方法B应该对待A的事务态度。(B是自己开启一个新事务,还是融入A的事务,或者不添加事务,或者…)
Spring事务角色 事务管理员 + 事务协调员
事务管理员一般是业务层,事务A
事务协调员一般是数据层,事务B
再次翻译下事务传播行为:事务传播行为是指事务协调员对于事务管理员的态度@Transactional中的propagation属性
下图来源于:B站视频,点击进入,,我觉得讲的很好,,建议大家去瞅瞅。。
案例:往面转账案例添加一个记录日志的功能,要求转账成功之后,要给account_log表插入谁向谁转了多少钱
-
添加一个数据表
create table account_log(out_id int,in_id int,money double );
-
dao层接口添加方法
public interface AccountDao {//转出@Update("update account set money = money - #{money} where id = #{outId}")int outMoney(@Param("outId") int outId, @Param("money")double money);//转入@Update("update account set money = money + #{money} where id = #{inId}")int inMoney(@Param("inId") int inId, @Param("money")double money);//记录日志@Insert("insert into account_log values(#{outId},#{inId},#{money})")void insertLog(@Param("outId") int outId, @Param("inId") int inId,@Param("money") double money); }
-
service层的AccountServiceImpl修改为
@Service public class AccountServiceImpl02 implements AccountService {@Autowiredprivate AccountDao dao;@Autowiredprivate DataSource dataSource;/**转账事务*/@Transactional(propagation = Propagation.REQUIRED)public void s1(int outId,int inId,double money){dao.outMoney(outId,money);//可能在转账过程中发生意外: 转出执行,转入还未执行dao.inMoney(inId,money);}/**记录日志事务*/@Transactional(propagation = Propagation.REQUIRES_NEW)public void s2(int outId,int inId,double money){dao.insertLog(outId,inId,money);}/**业务逻辑:1). 如果转账S1操作失败了, S1需要回滚(S1的操作肯定需要事务)如果S1有事务,S1跟随即可, 如果S1没有事务,S1需要自己创建事务所以S1适合设置传播行为属性为REQUIRED2). 如果S1成功,S2向数据库中插入日志如果转账S1操作失败了, S2不需要回滚,也向数据库中插入日志所以S2适合设置传播行为属性为REQUIRES_NEW */@Transactional@Overridepublic void transfer(int outId, int inId, double money) {s1(outId,inId,money); // int i = 10 / 0;s2(outId,inId,money);} }
相关文章:

Spring声明式事务以及事务传播行为
Spring声明式事务以及事务传播行为 Spring声明式事务1.编程式事务2.使用AOP改造编程式事务3.Spring声明式事务 事务传播行为 如果对数据库事务不太熟悉,可以阅读上一篇博客简单回顾一下:MySQL事务以及并发访问隔离级别 Spring声明式事务 事务一般添加到…...
【C语言数据库】Sqlite3基础介绍
1. SQLite简介 SQLite is a C-language library that implements a small, fast, self-contained, high-reliability, full-featured, SQL database engine. SQLite is the most used database engine in the world. SQLite is built into all mobile phones and most computer…...

el-upload上传图片图片、el-load默认图片重新上传、el-upload初始化图片、el-upload编辑时回显图片
问题 我用el-upload上传图片,再上一篇文章已经解决了,el-upload上传图片给SpringBoot后端,但是又发现了新的问题,果然bug是一个个的冒出来的。新的问题是el-upload编辑时回显图片的保存。 问题描述:回显图片需要将默认的 file-lis…...
【拓扑空间】示例及详解1
例1 度量空间的任意两球形邻域的交集是若干球形邻域的并集 Proof: 任取空间的两个球形邻域、,令 任取,令 球形领域 例2 规定X的子集族,证明是X上的一个拓扑 Proof: 1. 2., (若干个球形邻域的并集都是的元素,元素…...

linux安装jdk8
上传到某个目录,例如:/usr/local/ tar -xvf jdk-8u144-linux-x64.tar.gz配置环境变量: export JAVA_HOME/usr/local/java export PATH$PATH:$JAVA_HOME/bin设置环境变量: source /etc/profile...

Spring重点知识(个人整理笔记)
目录 1. 为什么要使用 spring? 2. 解释一下什么是 Aop? 3. AOP有哪些实现方式? 4. Spring AOP的实现原理 5. JDK动态代理和CGLIB动态代理的区别? 6. 解释一下什么是 ioc? 7. spring 有哪些主要模块?…...

HTML基础知识详解(上)(如何想知道html的全部基础知识点,那么只看这一篇就足够了!)
前言:在学习前端基础时,必不可少的就是三大件(html、css、javascript ),而HTML(超文本标记语言——HyperText Markup Language)是构成 Web 世界的一砖一瓦,它定义了网页内容的含义和…...

如何借助Idea创建多模块的SpringBoot项目
目录 1.1、前言1.2、开发环境1.3、项目多模块结构1.4、新建父工程1.5、创建子模块1.6、编辑父工程的pom.xml文件 1.1、前言 springmvc项目,一般会把项目分成多个包:controler、service、dao、utl等,但是随着项目的复杂性提高,想复用其他一个模…...

爬虫 新闻网站 并存储到CSV文件 以红网为例 V1.0
爬虫:红网网站, 获取当月指定关键词新闻,并存储到CSV文件 V1.0 目标网站:红网 爬取目的:为了获取某一地区更全面的在红网已发布的宣传新闻稿,同时也让自己的工作更便捷 环境:Pycharm2021&#…...
CentOS 使用 Cronie 实现定时任务
CentOS 使用 Cronie 实现定时任务 文章目录 CentOS 使用 Cronie 实现定时任务一、简介二、基本使用1、常用命令2、使用示例第一步:创建脚本/home/create.sh第二步:添加定时任务第三步:重启 cronie 服务额外:查看 cronie 运行状态定…...

java生成word
两种方案 一、poi-tl生成word <dependency><groupId>com.deepoove</groupId><artifactId>poi-tl</artifactId><version>1.12.1</version> </dependency> public static void main(String[] args) throws Exception {String…...

C语言中的结构体:揭秘数据的魔法盒
前言 在C语言的广阔天地中,结构体无疑是一颗璀璨的明珠。它就像是一个魔法盒,能够容纳各种不同类型的数据,并按我们的意愿进行组合和排列。那么,这个魔法盒究竟有何神奇之处呢?让我们一探究竟。 一、结构体的诞生&…...
Listener
文章目录 ListenerServletContextListenerServletContextAttributeListenerHttpSessionListenerHttpSessionAttributeListenerServletRequestListenerServletRequestAttributeListenerHttpSessionBindingListenerHttpSessionActivationListener Listener Listener 监听器它是 J…...

单细胞RNA测序(scRNA-seq)SRA数据下载及fastq-dumq数据拆分
单细胞RNA测序(scRNA-seq)入门可查看以下文章: 单细胞RNA测序(scRNA-seq)工作流程入门 单细胞RNA测序(scRNA-seq)细胞分离与扩增 1. NCBI查询scRNA-seq SRA数据 NCBI地址: https…...
金蝶Apusic应用服务器 未授权目录遍历漏洞复现
0x01 产品简介 金蝶Apusic应用服务器(Apusic Application Server,AAS)是一款标准、安全、高效、集成并具丰富功能的企业级应用服务器软件,全面支持JakartaEE8/9的技术规范,提供满足该规范的Web容器、EJB容器以及WebService容器等,支持Websocket1.1、Servlet4.0、HTTP2.0…...

成都百洲文化传媒有限公司电商服务的新领军者
在当今数字化时代,电商行业正以前所未有的速度蓬勃发展。在这个大背景下,成都百洲文化传媒有限公司凭借其深厚的行业经验和精湛的专业技能,正迅速崛起为电商服务领域的新领军者。 一、专业引领,成就卓越 作为一家专注于电商服务的…...
从无到有开始创建动态顺序表——C语言实现
顺序表的概念 顺序表的底层结构是数组,对数组的封装,实现了常用的增删改查等接口。在物理结构和逻辑结构都是连续的,物理结构是指顺序表在计算机内存的存储方式,逻辑结构是我们思考的形式,顺序表和数组是类似的&#x…...

Unix 网络编程, Socket 以及bind(), listen(), accept(), connect(), read()write()五大函数简介
Unix网络编程是针对类Unix操作系统(包括Linux、BSD以及其他遵循POSIX标准的操作系统)进行网络通信开发的技术领域。网络编程涉及创建和管理网络连接、交换数据以及处理不同层次网络协议栈上的各种网络事件。在Unix环境中,网络编程通常涉及到以…...

【附下载】2024全行业数字化转型企业建设解决方案PPT合集
精品推荐,2024全行业数字化转型企业建设解决方案PPT合集,精品PPT源格式共21份。 以下是资料目录,如需下载,请前往星球获取: 1.制造业数字化转型解决方案及应用.pptx 2.医院数字化网络解决方案.pptx 3.食品饮料工厂数字…...

【QT+QGIS跨平台编译】056:【pdal_lepcc+Qt跨平台编译】(一套代码、一套框架,跨平台编译)
点击查看专栏目录 文章目录 一、pdal_lepcc介绍二、pdal下载三、文件分析四、pro文件五、编译实践一、pdal_lepcc介绍 pdal_lepcc 是 PDAL(Point Data Abstraction Library)的一个插件,用于点云数据的压缩。它基于 EPCC(Entwine Point Cloud Compression)算法,提供了对点…...

网络编程(Modbus进阶)
思维导图 Modbus RTU(先学一点理论) 概念 Modbus RTU 是工业自动化领域 最广泛应用的串行通信协议,由 Modicon 公司(现施耐德电气)于 1979 年推出。它以 高效率、强健性、易实现的特点成为工业控制系统的通信标准。 包…...

基于距离变化能量开销动态调整的WSN低功耗拓扑控制开销算法matlab仿真
目录 1.程序功能描述 2.测试软件版本以及运行结果展示 3.核心程序 4.算法仿真参数 5.算法理论概述 6.参考文献 7.完整程序 1.程序功能描述 通过动态调整节点通信的能量开销,平衡网络负载,延长WSN生命周期。具体通过建立基于距离的能量消耗模型&am…...
FFmpeg 低延迟同屏方案
引言 在实时互动需求激增的当下,无论是在线教育中的师生同屏演示、远程办公的屏幕共享协作,还是游戏直播的画面实时传输,低延迟同屏已成为保障用户体验的核心指标。FFmpeg 作为一款功能强大的多媒体框架,凭借其灵活的编解码、数据…...

【入坑系列】TiDB 强制索引在不同库下不生效问题
文章目录 背景SQL 优化情况线上SQL运行情况分析怀疑1:执行计划绑定问题?尝试:SHOW WARNINGS 查看警告探索 TiDB 的 USE_INDEX 写法Hint 不生效问题排查解决参考背景 项目中使用 TiDB 数据库,并对 SQL 进行优化了,添加了强制索引。 UAT 环境已经生效,但 PROD 环境强制索…...
C++.OpenGL (10/64)基础光照(Basic Lighting)
基础光照(Basic Lighting) 冯氏光照模型(Phong Lighting Model) #mermaid-svg-GLdskXwWINxNGHso {font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}#mermaid-svg-GLdskXwWINxNGHso .error-icon{fill:#552222;}#mermaid-svg-GLd…...

NLP学习路线图(二十三):长短期记忆网络(LSTM)
在自然语言处理(NLP)领域,我们时刻面临着处理序列数据的核心挑战。无论是理解句子的结构、分析文本的情感,还是实现语言的翻译,都需要模型能够捕捉词语之间依时序产生的复杂依赖关系。传统的神经网络结构在处理这种序列依赖时显得力不从心,而循环神经网络(RNN) 曾被视为…...
高防服务器能够抵御哪些网络攻击呢?
高防服务器作为一种有着高度防御能力的服务器,可以帮助网站应对分布式拒绝服务攻击,有效识别和清理一些恶意的网络流量,为用户提供安全且稳定的网络环境,那么,高防服务器一般都可以抵御哪些网络攻击呢?下面…...
AGain DB和倍数增益的关系
我在设置一款索尼CMOS芯片时,Again增益0db变化为6DB,画面的变化只有2倍DN的增益,比如10变为20。 这与dB和线性增益的关系以及传感器处理流程有关。以下是具体原因分析: 1. dB与线性增益的换算关系 6dB对应的理论线性增益应为&…...
LangChain知识库管理后端接口:数据库操作详解—— 构建本地知识库系统的基础《二》
这段 Python 代码是一个完整的 知识库数据库操作模块,用于对本地知识库系统中的知识库进行增删改查(CRUD)操作。它基于 SQLAlchemy ORM 框架 和一个自定义的装饰器 with_session 实现数据库会话管理。 📘 一、整体功能概述 该模块…...

RSS 2025|从说明书学习复杂机器人操作任务:NUS邵林团队提出全新机器人装配技能学习框架Manual2Skill
视觉语言模型(Vision-Language Models, VLMs),为真实环境中的机器人操作任务提供了极具潜力的解决方案。 尽管 VLMs 取得了显著进展,机器人仍难以胜任复杂的长时程任务(如家具装配),主要受限于人…...