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)算法,提供了对点…...
synchronized 学习
学习源: https://www.bilibili.com/video/BV1aJ411V763?spm_id_from333.788.videopod.episodes&vd_source32e1c41a9370911ab06d12fbc36c4ebc 1.应用场景 不超卖,也要考虑性能问题(场景) 2.常见面试问题: sync出…...

python打卡day49
知识点回顾: 通道注意力模块复习空间注意力模块CBAM的定义 作业:尝试对今天的模型检查参数数目,并用tensorboard查看训练过程 import torch import torch.nn as nn# 定义通道注意力 class ChannelAttention(nn.Module):def __init__(self,…...
PHP和Node.js哪个更爽?
先说结论,rust完胜。 php:laravel,swoole,webman,最开始在苏宁的时候写了几年php,当时觉得php真的是世界上最好的语言,因为当初活在舒适圈里,不愿意跳出来,就好比当初活在…...
postgresql|数据库|只读用户的创建和删除(备忘)
CREATE USER read_only WITH PASSWORD 密码 -- 连接到xxx数据库 \c xxx -- 授予对xxx数据库的只读权限 GRANT CONNECT ON DATABASE xxx TO read_only; GRANT USAGE ON SCHEMA public TO read_only; GRANT SELECT ON ALL TABLES IN SCHEMA public TO read_only; GRANT EXECUTE O…...

CocosCreator 之 JavaScript/TypeScript和Java的相互交互
引擎版本: 3.8.1 语言: JavaScript/TypeScript、C、Java 环境:Window 参考:Java原生反射机制 您好,我是鹤九日! 回顾 在上篇文章中:CocosCreator Android项目接入UnityAds 广告SDK。 我们简单讲…...
python如何将word的doc另存为docx
将 DOCX 文件另存为 DOCX 格式(Python 实现) 在 Python 中,你可以使用 python-docx 库来操作 Word 文档。不过需要注意的是,.doc 是旧的 Word 格式,而 .docx 是新的基于 XML 的格式。python-docx 只能处理 .docx 格式…...
Python如何给视频添加音频和字幕
在Python中,给视频添加音频和字幕可以使用电影文件处理库MoviePy和字幕处理库Subtitles。下面将详细介绍如何使用这些库来实现视频的音频和字幕添加,包括必要的代码示例和详细解释。 环境准备 在开始之前,需要安装以下Python库:…...
Caliper 配置文件解析:config.yaml
Caliper 是一个区块链性能基准测试工具,用于评估不同区块链平台的性能。下面我将详细解释你提供的 fisco-bcos.json 文件结构,并说明它与 config.yaml 文件的关系。 fisco-bcos.json 文件解析 这个文件是针对 FISCO-BCOS 区块链网络的 Caliper 配置文件,主要包含以下几个部…...

DingDing机器人群消息推送
文章目录 1 新建机器人2 API文档说明3 代码编写 1 新建机器人 点击群设置 下滑到群管理的机器人,点击进入 添加机器人 选择自定义Webhook服务 点击添加 设置安全设置,详见说明文档 成功后,记录Webhook 2 API文档说明 点击设置说明 查看自…...

关于easyexcel动态下拉选问题处理
前些日子突然碰到一个问题,说是客户的导入文件模版想支持部分导入内容的下拉选,于是我就找了easyexcel官网寻找解决方案,并没有找到合适的方案,没办法只能自己动手并分享出来,针对Java生成Excel下拉菜单时因选项过多导…...