Spring和Spring Boot事务讲解和案例示范
引言
Spring框架提供了强大的事务管理支持,使得开发者能够更轻松地实现事务控制。在本篇文章中,我们将深入探讨Spring的事务管理机制,特别是编程式事务管理、声明式事务管理以及在多数据源环境下的事务处理。
第一章 编程式事务管理
编程式事务管理是指开发者在代码中手动控制事务的生命周期。对于基于POJO(Plain Old Java Object)的应用,这种方式是唯一的选择。编程式事务管理通常使用Spring的TransactionManager
接口来实现事务的开始、提交和回滚。以下是编程式事务管理的一些重要概念和步骤。
1. 编程式事务管理的基本步骤
在编程式事务管理中,开发者需要显式地调用beginTransaction()
、commit()
和rollback()
等方法来管理事务。以下是实现这一过程的步骤:
- 获取
PlatformTransactionManager
实例:通过Spring的应用上下文获取事务管理器实例。 - 创建事务定义:定义事务的传播行为和隔离级别等属性。
- 开始事务:通过事务管理器的
getTransaction()
方法获取当前事务。 - 执行业务逻辑:在事务中执行需要原子性的数据操作。
- 提交或回滚事务:根据业务逻辑的执行结果选择提交或回滚。
2. 示例代码
下面是一个简单的电子商务交易系统中编程式事务管理的示例代码。假设我们有一个OrderService
类,用于处理订单的创建:
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.transaction.PlatformTransactionManager;
import org.springframework.transaction.TransactionStatus;
import org.springframework.transaction.support.DefaultTransactionDefinition;public class OrderService {@Autowiredprivate PlatformTransactionManager transactionManager;public void createOrder(Order order) {// 定义事务属性DefaultTransactionDefinition def = new DefaultTransactionDefinition();def.setPropagationBehavior(DefaultTransactionDefinition.PROPAGATION_REQUIRED);// 开始事务TransactionStatus status = transactionManager.getTransaction(def);try {// 执行业务逻辑,例如保存订单saveOrder(order);// 提交事务transactionManager.commit(status);} catch (Exception e) {// 回滚事务transactionManager.rollback(status);throw new RuntimeException("Failed to create order", e);}}private void saveOrder(Order order) {// 保存订单到数据库的逻辑}
}
在上面的代码中,我们首先定义了事务的传播行为为PROPAGATION_REQUIRED
,这意味着如果当前存在事务,则加入该事务;否则新建一个事务。接着,通过transactionManager.getTransaction(def)
开始事务,执行业务逻辑后根据情况决定提交或回滚事务。
3. 编程式事务管理的优缺点
优点:
- 灵活性高:开发者可以在代码中完全控制事务的执行过程,适合复杂业务逻辑的处理。
- 透明性:可以清晰地看到每一步的事务处理过程,便于调试。
缺点:
- 代码冗长:每次处理事务都需要写大量的代码,降低了可读性和可维护性。
- 容易出错:手动管理事务增加了出错的可能性,尤其是在复杂的业务流程中。
第二章 声明式事务管理
声明式事务管理是Spring框架提供的一种简化事务处理的方式,允许开发者通过配置而非代码控制事务的行为。这种方式大大降低了代码的复杂性,提升了可维护性和可读性。声明式事务管理可以通过XML配置或者注解(如@Transactional
)来实现。
1. 使用TransactionProxyFactoryBean
TransactionProxyFactoryBean
是Spring提供的一种基于代理的声明式事务管理方式。通过配置此Bean,开发者可以定义事务的边界,而不需要在业务逻辑中显式地处理事务。
示例代码:
首先,在Spring的配置文件中定义一个TransactionProxyFactoryBean
:
<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager"><property name="dataSource" ref="dataSource"/>
</bean><bean id="orderService" class="com.example.OrderService"><property name="dataSource" ref="dataSource"/>
</bean><bean id="transactionProxy" class="org.springframework.transaction.interceptor.TransactionProxyFactoryBean"><property name="target" ref="orderService"/><property name="transactionManager" ref="transactionManager"/><property name="transactionAttributes"><map><entry key="createOrder" value="PROPAGATION_REQUIRED"/></map></property>
</bean>
在上面的示例中,TransactionProxyFactoryBean
将OrderService
作为目标Bean,定义createOrder
方法的事务属性为PROPAGATION_REQUIRED
。
2. 基于@Transactional
的声明式事务管理
随着Spring 2.0引入的@Transactional
注解,声明式事务管理变得更加简单和直观。通过在方法或类上添加该注解,开发者可以指定该方法或类所需的事务属性。
示例代码:
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;@Service
public class OrderService {@Transactional(propagation = Propagation.REQUIRED)public void createOrder(Order order) {// 保存订单逻辑saveOrder(order);}private void saveOrder(Order order) {// 数据库保存逻辑}
}
在上面的代码中,@Transactional
注解自动为createOrder
方法添加了事务管理,开发者不再需要手动管理事务的开始和提交。
3. 事务传播行为
Spring定义了多种事务传播行为,开发者可以根据业务需求选择合适的策略。常用的传播行为包括:
PROPAGATION_REQUIRED
:如果当前有事务,则加入该事务;否则新建一个事务。PROPAGATION_REQUIRES_NEW
:总是新建一个事务。PROPAGATION_NESTED
:如果当前有事务,则嵌套事务;否则新建一个事务。
第三章 基于AspectJ的AOP配置事务
AspectJ是Spring提供的强大AOP支持,能够在方法执行前后进行横切逻辑处理。在基于AspectJ的配置中,事务管理是通过切面(Aspect)来实现的,这样可以将事务逻辑与业务逻辑分离,使得代码更加清晰。
1. AspectJ事务管理的配置
为了使用AspectJ配置事务管理,首先需要在Spring配置中启用AspectJ支持:
<beans xmlns="http://www.springframework.org/schema/beans"xmlns:aop="http://www.springframework.org/schema/aop"xmlns:context="http://www.springframework.org/schema/context"xmlns:tx="http://www.springframework.org/schema/tx"xsi:schemaLocation="http://www.springframework.org/schema/beanshttp://www.springframework.org/schema/beans/spring-beans.xsdhttp://www.springframework.org/schema/aophttp://www.springframework.org/schema/aop/spring-aop.xsdhttp://www.springframework.org/schema/contexthttp://www.springframework.org/schema/context/spring-context.xsdhttp://www.springframework.org/schema/txhttp://www.springframework.org/schema/tx/spring-tx.xsd"><tx:annotation-driven transaction-manager="transactionManager"/><bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager"><property name="dataSource" ref="dataSource"/></bean></beans>
2. 创建切面
接下来,创建一个切面类来处理事务逻辑:
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.springframework.transaction.annotation.Transactional;@Aspect
public class TransactionAspect {@Pointcut("execution(* com.example..*(..))") // 定义切入点public void transactionPointcut() {}@Transactionalpublic void aroundTransaction(ProceedingJoinPoint joinPoint) throws Throwable {try {joinPoint.proceed(); // 执行目标方法} catch (Throwable ex) {// 处理异常逻辑throw ex;}}
}
在上面的代码中,TransactionAspect
类定义了一个切入点,用于匹配com.example
包下的所有方法,并在方法执行前后处理事务。
3. 优缺点分析
优点:
- 解耦性:业务逻辑与事务逻辑分离,提高了代码的可读性。
- 可复用性:切面可以在多个业务逻辑中复用,减少代码重复。
缺点:
- 学习曲线:对于初学者来说,AOP的概念和配置可能会增加学习难度。
- 性能开销:切面处理增加了一定的性能开销,尤其是在高频调用的场景下。
第四章 多数据源下的事务管理
在复杂的电子商务系统中,往往需要使用多个数据源来存储不同类型的数据。例如,一个系统可能需要一个数据源来存储用户信息,另一个数据源来存储订单数据。处理多数据源的事务管理是一个重要的挑战,因为不同的数据源之间的事务管理需要确保一致性和隔离性。
1. 多数据源的配置
在Spring中,可以通过配置多个DataSource
来支持多数据源。以下是一个简单的多数据源配置示例:
<bean id="dataSource1" class="org.apache.commons.dbcp.BasicDataSource"><property name="driverClassName" value="com.mysql.jdbc.Driver"/><property name="url" value="jdbc:mysql://localhost:3306/db1"/><property name="username" value="user1"/><property name="password" value="password1"/>
</bean><bean id="dataSource2" class="org.apache.commons.dbcp.BasicDataSource"><property name="driverClassName" value="com.mysql.jdbc.Driver"/><property name="url" value="jdbc:mysql://localhost:3306/db2"/><property name="username" value="user2"/><property name="password" value="password2"/>
</bean>
2. 配置事务管理器
对于多数据源,我们需要配置一个ChainedTransactionManager
,以便在同一个事务中管理多个数据源:
<bean id="transactionManager" class="org.springframework.transaction.support.TransactionSynchronizationManager"><property name="transactionManagers"><list><ref bean="dataSource1TransactionManager"/><ref bean="dataSource2TransactionManager"/></list></property>
</bean><bean id="dataSource1TransactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager"><property name="dataSource" ref="dataSource1"/>
</bean><bean id="dataSource2TransactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager"><property name="dataSource" ref="dataSource2"/>
</bean>
3. 使用@Transactional
管理多数据源事务
在多数据源的场景中,使用@Transactional
注解时需要明确指定事务管理器,以确保事务能够跨多个数据源进行管理:
import org.springframework.transaction.annotation.Transactional;public class OrderService {@Transactional(transactionManager = "transactionManager")public void createOrder(Order order, User user) {// 保存订单到dataSource1saveOrder(order);// 保存用户到dataSource2saveUser(user);}
}
在上述代码中,@Transactional
注解的transactionManager
属性指定了事务管理器,这样可以确保在createOrder
方法中对多个数据源的操作都在同一个事务内执行。
4. 事务的一致性与隔离性
在多数据源环境下,确保事务的一致性和隔离性是非常重要的。开发者需要关注以下几个方面:
- 事务传播行为:确保操作在同一事务中执行,避免出现部分提交的情况。
- 隔离级别:根据业务需求选择合适的隔离级别,防止数据竞争和不可重复读等问题。
第五章 rollbackFor
属性
1. 默认事务回滚行为
默认情况下,Spring对事务的回滚行为如下:
- 自动回滚:当抛出
RuntimeException
或其子类异常时,事务会自动回滚。 - 不回滚:当抛出
Exception
(即检查型异常)时,事务不会自动回滚,除非显式指定。
例如,以下代码在抛出 RuntimeException
时会回滚事务,但抛出 Exception
时不会回滚:
@Transactional
public void processOrder(Order order) throws Exception {// 订单处理逻辑if (someConditionFails()) {throw new Exception("订单处理失败!"); // 默认不会回滚事务}if (someOtherConditionFails()) {throw new RuntimeException("订单处理过程中出现运行时错误!"); // 默认会回滚事务}
}
在上述示例中,Exception
是检查型异常,Spring不会自动回滚它引发的事务。
2. 使用 rollbackFor
属性进行异常回滚控制
如果我们希望在抛出 Exception
或其他检查型异常时也回滚事务,可以通过 @Transactional
注解的 rollbackFor
属性来指定需要回滚的异常类型。
示例:指定在抛出 Exception
时回滚事务
@Transactional(rollbackFor = Exception.class)
public void processOrder(Order order) throws Exception {// 订单处理逻辑if (someConditionFails()) {throw new Exception("订单处理失败!"); // 现在会回滚事务}if (someOtherConditionFails()) {throw new RuntimeException("订单处理过程中出现运行时错误!"); // 依然会回滚事务}
}
在这个示例中,@Transactional(rollbackFor = Exception.class)
明确指定了当 Exception
被抛出时,事务也会回滚。
使用多个异常类型
可以指定多个异常类型,在多个异常类型下触发事务回滚:
@Transactional(rollbackFor = {Exception.class, SQLException.class})
public void processOrder(Order order) throws Exception {// 订单处理逻辑if (someConditionFails()) {throw new SQLException("数据库异常!"); // 现在会回滚事务}if (someOtherConditionFails()) {throw new Exception("订单处理失败!"); // 现在会回滚事务}
}
3. 在电商交易系统中的应用示例
在电商交易系统中,处理订单的过程中可能会发生多种不同类型的异常。比如,订单处理中可能抛出数据库相关的 SQLException
,或者业务逻辑失败的 BusinessException
。我们可以通过 rollbackFor
指定这些异常类型,以确保订单处理过程中发生这些异常时事务会正确回滚。
示例:电商系统中的订单处理
public class OrderService {@Transactional(rollbackFor = {SQLException.class, BusinessException.class})public void processOrder(Order order) throws BusinessException, SQLException {// 更新库存updateInventory(order);// 扣款操作if (!deductPayment(order)) {throw new BusinessException("扣款失败!");}// 提交订单if (!submitOrder(order)) {throw new SQLException("订单提交失败!");}}private void updateInventory(Order order) {// 库存更新逻辑}private boolean deductPayment(Order order) {// 扣款逻辑return false; // 模拟扣款失败}private boolean submitOrder(Order order) throws SQLException {// 订单提交逻辑return false; // 模拟数据库异常}
}
在上述示例中:
- 如果
deductPayment
方法失败,会抛出BusinessException
,这将导致事务回滚。 - 如果
submitOrder
方法失败,抛出的SQLException
也会触发事务回滚。
第六章 Spring Boot 中使用 @Transactional
注解
在Spring Boot项目中,使用@Transactional
注解非常简单,它主要用于控制业务逻辑中的事务处理,确保数据库操作的原子性。Spring Boot自动集成了事务管理,因此你无需进行过多的配置,只需要在方法或类上使用@Transactional
注解即可。
1. Spring Boot 中的基本事务配置
默认情况下,Spring Boot会自动为你的项目启用事务管理。你只需要添加以下依赖:
Maven依赖:
<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
Spring Boot使用spring-boot-starter-data-jpa
为JPA提供支持,事务管理器会自动配置。
2. 启用事务管理
在Spring Boot中,事务管理默认是启用的。如果你使用的是非Spring Boot项目,你可能需要使用@EnableTransactionManagement
注解来启用事务管理。但在Spring Boot中,默认就支持该功能,无需额外配置。
如果需要显式启用,可以通过在配置类上添加@EnableTransactionManagement
注解:
@Configuration
@EnableTransactionManagement
public class TransactionConfig {// 自定义事务管理器(如果需要)
}
3. 使用 @Transactional
注解
@Transactional
注解可以用在类或方法上,控制在这些方法中的所有数据库操作是否作为一个事务执行。默认情况下,它会对运行时异常进行回滚。
在方法上使用 @Transactional
@Service
public class OrderService {@Autowiredprivate OrderRepository orderRepository;@Transactionalpublic void processOrder(Order order) {// 执行数据库操作,例如保存订单orderRepository.save(order);// 执行其他相关操作,例如更新库存updateInventory(order);// 如果任何操作失败,抛出异常,事务将回滚if (!order.isValid()) {throw new RuntimeException("订单验证失败,事务回滚!");}}private void updateInventory(Order order) {// 更新库存逻辑}
}
在上面的示例中,processOrder
方法标记为@Transactional
,如果方法中抛出了RuntimeException
或其子类的异常,所有的数据库操作都会被回滚。
在类上使用 @Transactional
你也可以将@Transactional
注解应用于类上,标记类中的所有公共方法都参与事务管理:
@Service
@Transactional
public class OrderService {@Autowiredprivate OrderRepository orderRepository;public void processOrder(Order order) {orderRepository.save(order);}public void cancelOrder(Long orderId) {orderRepository.deleteById(orderId);}
}
在这个类中,processOrder
和cancelOrder
方法都将在事务中运行,任何一个方法抛出异常都会导致事务回滚。
4. 事务的传播行为和隔离级别
你可以通过@Transactional
注解的属性自定义事务的传播行为和隔离级别:
- 传播行为:可以通过
propagation
属性控制,默认值为Propagation.REQUIRED
。例如,如果一个事务已经存在,Spring将加入到该事务中;如果不存在,则创建一个新的事务。
@Transactional(propagation = Propagation.REQUIRES_NEW)
public void createNewOrder(Order order) {orderRepository.save(order);
}
- 隔离级别:可以通过
isolation
属性设置,控制数据库并发访问的行为。默认值为Isolation.DEFAULT
,即使用数据库的默认隔离级别。
@Transactional(isolation = Isolation.SERIALIZABLE)
public void updateOrder(Order order) {orderRepository.save(order);
}
5. 完整的 Spring Boot 事务管理案例
接下来,我们将构建一个完整的Spring Boot事务管理示例,展示如何使用@Transactional
注解处理事务。
项目结构
src├── main│ ├── java│ │ └── com.example.transactiondemo│ │ ├── TransactionDemoApplication.java│ │ ├── model│ │ │ └── Order.java│ │ ├── repository│ │ │ └── OrderRepository.java│ │ └── service│ │ └── OrderService.java├── resources│ └── application.properties
5.1 Order
实体类
package com.example.transactiondemo.model;import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;@Entity
public class Order {@Id@GeneratedValue(strategy = GenerationType.IDENTITY)private Long id;private String description;private boolean valid;// Getters and Setters
}
5.2 OrderRepository
接口
package com.example.transactiondemo.repository;import com.example.transactiondemo.model.Order;
import org.springframework.data.jpa.repository.JpaRepository;public interface OrderRepository extends JpaRepository<Order, Long> {
}
5.3 OrderService
服务类
package com.example.transactiondemo.service;import com.example.transactiondemo.model.Order;
import com.example.transactiondemo.repository.OrderRepository;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;@Service
public class OrderService {@Autowiredprivate OrderRepository orderRepository;@Transactionalpublic void processOrder(Order order) {// 保存订单orderRepository.save(order);// 假设更新库存出错,抛出异常if (!order.isValid()) {throw new RuntimeException("订单无效,事务回滚!");}}@Transactionalpublic void cancelOrder(Long orderId) {orderRepository.deleteById(orderId);}
}
5.4 TransactionDemoApplication
应用启动类
package com.example.transactiondemo;import com.example.transactiondemo.model.Order;
import com.example.transactiondemo.service.OrderService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.CommandLineRunner;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;@SpringBootApplication
public class TransactionDemoApplication implements CommandLineRunner {@Autowiredprivate OrderService orderService;public static void main(String[] args) {SpringApplication.run(TransactionDemoApplication.class, args);}@Overridepublic void run(String... args) throws Exception {// 创建并处理订单Order order = new Order();order.setDescription("新订单");order.setValid(false); // 模拟订单无效,抛出异常回滚事务try {orderService.processOrder(order);} catch (RuntimeException e) {System.out.println("事务回滚,订单处理失败!");}}
}
5.5 配置文件 application.properties
spring.datasource.url=jdbc:mysql://localhost:3306/transactiondemo
spring.datasource.username=root
spring.datasource.password=password
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
spring.jpa.hibernate.ddl-auto=update
5.6 运行结果
当运行该应用程序时,创建的订单由于 valid
属性设置为 false
,会触发异常,导致事务回滚。数据库中不会插入该订单的数据,保证了数据的完整性和一致性。
第七章 常见问题及解决方案
在实际开发中,使用Spring事务管理时可能会遇到一些常见问题。以下是一些常见问题及其解决方案:
1. 事务未生效
问题:在使用@Transactional
时,事务未生效,方法执行后数据仍然被提交。
解决方案:
- 确保方法是public的,Spring的代理机制要求事务方法必须是公共的。
- 确保使用
@Transactional
注解的方法被Spring管理,即该方法不能在同一类中被直接调用。
2. 数据库连接泄漏
问题:由于长时间未关闭数据库连接,导致连接池资源耗尽。
解决方案:
- 确保在每个事务结束后正确关闭连接,Spring会自动处理事务结束时的连接释放。
- 在使用编程式事务时,确保在异常处理逻辑中回滚事务并关闭连接。
3. 事务回滚未生效
问题:当异常发生时,事务未按预期回滚。
解决方案:
- 默认情况下,Spring只会对运行时异常(
RuntimeException
)进行回滚,确保抛出的异常类型是运行时异常。 - 可以在
@Transactional
注解中设置rollbackFor
属性,指定需要回滚的异常类型。
4. 多数据源事务管理问题
问题:在多数据源环境下,事务提交不一致,部分数据提交成功,部分数据失败。
解决方案:
- 确保使用
ChainedTransactionManager
或类似的事务管理器来处理多个数据源的事务。 - 检查每个数据源的事务配置,确保一致性和正确的事务传播行为。
相关文章:
Spring和Spring Boot事务讲解和案例示范
引言 Spring框架提供了强大的事务管理支持,使得开发者能够更轻松地实现事务控制。在本篇文章中,我们将深入探讨Spring的事务管理机制,特别是编程式事务管理、声明式事务管理以及在多数据源环境下的事务处理。 第一章 编程式事务管理 编程式…...
前端的全栈混合之路Meteor篇:关于前后端分离及与各框架的对比
这篇属于番外,属于技术性的讨论文,主要谈一下可能困惑不少人的问题。meteor看似一个前后端混合的框架,但实际上它并不是前后端混合的,只是共享了一个数据结构(数据对象)。现实中很多团队都说是前后端分离的…...

OJ在线评测系统 微服务 OpenFeign调整后端下 nacos注册中心配置 不给前端调用的代码 全局引入负载均衡器
OpenFeign内部调用二 4.修改各业务服务的调用代码为feignClient 开启nacos注册 把Client变成bean 该服务仅内部调用,不是给前端的 将某个服务标记为“内部调用”的目的主要有以下几个方面: 安全性: 内部API通常不对外部用户公开,这样可以防止…...
QD1-P19 HTML 总结
本节简单总结:《前端学习笔记1》专题前18篇文章关于HTML的内容。 下一节开始学习CSS了。HTML还是挺易学的,比Linux命令容易。 本节视频 www.bilibili.com/video/BV1n64y1U7oj?p19 在前面18节中,我们了解了HTML的基础知识: …...

Android Framework AMS(03)AMS关键类解读
该系列文章总纲链接:专题总纲目录 Android Framework 总纲 本章关键点总结 & 说明: 说明:本章节主要涉AMS的关键类及其设计理念的解读,主要关注图中下方AMS关键类解读部分即可。这么做的目的是为了后面章节分析AMS时更容易理解…...
Pygame开发贪吃蛇
Pygame专为Python设计,支持多平台(如Windows、Mac OS X、Linux、Android等),提供简单易用的API来创建2D游戏。它不仅仅局限于游戏开发,还可用于图形界面和音频应用。 Pygame提供了简洁的API,使得开发者可以…...

Linux进程间通信(个人笔记)
Linux进程通信 1.进程通信介绍1.1进程间通信目的1.2进程间通信发展1.3进程间通信的具体分类 2.管道2.1匿名管道2.1.1代码实例2.1.2 fork共享管道原理2.1.3 管道的读写规则与特点2.1.4 进程池 2.2 命名管道2.2.1 命名管道的创建2.2.2匿名管道与命名管道的区别2.2.3代码实例 3.Sy…...
SAP S/4HANA 迁移:IT 高管实用指南
新版《通往SAP S/4HANA之路》指南为计划从SAP ERP或SAP S/4HANA本地版本迁移到云端的组织提供了全面的参考。随着数字化转型的加速,尤其是在面临挑战的汽车行业等领域,企业必须采用云ERP解决方案,例如SAP S/4HANA云私有版,以应对瞬…...

Qt源码-Qt多媒体音频框架
Qt 多媒体音频框架 一、概述二、音频设计1. ALSA 基础2. Qt 音频类1. 接口实现2. alsa 插件实现 一、概述 环境详细Qt版本Qt 5.15操作系统Deepin v23代码工具Visual Code源码https://github.com/qt/qtmultimedia/tree/5.15 这里记录一下在Linux下Qt 的 Qt Multimedia 模块的设…...

卸载PLSQL及标准卸载流程
目录 1. 卸载PLSQL2. 删除注册表3. 删除数据信息 1. 卸载PLSQL 等待进度条走完 2. 删除注册表 regedit 右击删除 3. 删除数据信息 由于AppData是隐藏文件,需要勾选隐藏的项目。 重启电脑,PLSQL就卸载成功了。...

如何使用ssm实现办公OA系统0
TOC 10907ssm办公OA系统10907ssm0 第一章 绪 论 1.1背景及意义 系统管理也都将通过计算机进行整体智能化操作,对于办公OA系统所牵扯的管理及数据保存都是非常多的,例如管理员;主页、个人中心、公司公告管理、设备分类管理、办公设备管理、…...

IPguard与Ping32—选择合适的企业数据保护解决方案
在数字化时代,企业面临着各种数据安全挑战,选择合适的保护工具至关重要。IPguard与Ping32是两款备受关注的数据保护软件,但它们各自的功能和适用场景有所不同,企业在选择时需根据自身需求做出明智决策。 Ping32:全面的…...

2024 kali虚拟机安装教程,分两大步骤,图文讲解(2)
准备工作: 按照图文讲解(1)搭建好虚拟机,继续以下步骤 2024 kali虚拟机安装教程,分两大步骤,图文讲解(1)-CSDN博客 正式开始 1.开启,↑ ↓ 方向键,选择第一…...

【解决办法】git clone报错unable to access ‘xxx‘: SSL certificate problem
git clone 是 Git 版本控制系统中的一个基本命令,用于从远程仓库复制一个完整的版本库到本地。这个命令不仅复制远程仓库中的所有文件,还复制仓库的历史记录,使得你可以在本地进行版本控制操作,如提交(commitÿ…...

基于STM32的智能家居--硬件接线
分配GPIO 1.首先分配串口通讯引脚,该开发板中有三组串口引脚分别分配如图所示。 2.分配SPI。 3.其他为普通GPIO口,B8,B9模拟IIC协议与OLED屏幕进行通讯。...

mac电脑如何删除应用程序?怎么删除苹果电脑里的软件
在使用Mac电脑的过程中,随着时间的推移,我们可能会安装大量的应用程序。然而,这些应用程序中有很多可能只是临时使用,或者已经不再需要了。这些无用的应用程序不仅占据了宝贵的硬盘空间,还可能拖慢Mac系统的运行速度。…...
Hive优化操作(一)
Hive SQL 优化指南 在使用 Hive 进行数据分析时,提高查询性能至关重要。以下是一些具体的优化策略,帮助我们在工作中更有效地管理和查询数据。 一、 减少数据量进行优化 1. 分区表优化 分区是一种表的子集,用于按某一列(如日期…...
Vue中常用指令——(详解,并附有代码)
文章目录 一.指令合集1.0 概述1.1 插值表达式1.2 v-text/v-html1.3 v-show/ v-if1.4 v-on1.4.1 内联语句1.4.2 事件处理函数 1.5 v-bind1.6 Test1.7 v-for 一.指令合集 内容渲染指令(v-html、v-text)条件渲染指令(v-show、v-if、v-else、v-e…...
redistemplate实现点赞相关功能
使用Redis的SET数据结构来存储每个实体的点赞用户ID列表,方便进行点赞数量的计数和用户点赞状态的检查。以下是一个小demo,只提供简单思路。 Service public class LikeService {Autowiredprivate RedisTemplate redisTemplate;//点赞public Long like(…...

C++ 算法学习——7.4.1 优化算法——双指针
双指针法(Two Pointers)是一种常用的算法技巧,通常用于解决数组或链表中的问题。这种技巧通过维护两个指针,通常分别指向数组或链表的不同位置,来协同解决问题。双指针法一般有两种类型:快慢指针和左右指针…...
KubeSphere 容器平台高可用:环境搭建与可视化操作指南
Linux_k8s篇 欢迎来到Linux的世界,看笔记好好学多敲多打,每个人都是大神! 题目:KubeSphere 容器平台高可用:环境搭建与可视化操作指南 版本号: 1.0,0 作者: 老王要学习 日期: 2025.06.05 适用环境: Ubuntu22 文档说…...

【CSS position 属性】static、relative、fixed、absolute 、sticky详细介绍,多层嵌套定位示例
文章目录 ★ position 的五种类型及基本用法 ★ 一、position 属性概述 二、position 的五种类型详解(初学者版) 1. static(默认值) 2. relative(相对定位) 3. absolute(绝对定位) 4. fixed(固定定位) 5. sticky(粘性定位) 三、定位元素的层级关系(z-i…...

基于Docker Compose部署Java微服务项目
一. 创建根项目 根项目(父项目)主要用于依赖管理 一些需要注意的点: 打包方式需要为 pom<modules>里需要注册子模块不要引入maven的打包插件,否则打包时会出问题 <?xml version"1.0" encoding"UTF-8…...

tree 树组件大数据卡顿问题优化
问题背景 项目中有用到树组件用来做文件目录,但是由于这个树组件的节点越来越多,导致页面在滚动这个树组件的时候浏览器就很容易卡死。这种问题基本上都是因为dom节点太多,导致的浏览器卡顿,这里很明显就需要用到虚拟列表的技术&…...
Linux离线(zip方式)安装docker
目录 基础信息操作系统信息docker信息 安装实例安装步骤示例 遇到的问题问题1:修改默认工作路径启动失败问题2 找不到对应组 基础信息 操作系统信息 OS版本:CentOS 7 64位 内核版本:3.10.0 相关命令: uname -rcat /etc/os-rele…...

【分享】推荐一些办公小工具
1、PDF 在线转换 https://smallpdf.com/cn/pdf-tools 推荐理由:大部分的转换软件需要收费,要么功能不齐全,而开会员又用不了几次浪费钱,借用别人的又不安全。 这个网站它不需要登录或下载安装。而且提供的免费功能就能满足日常…...

论文阅读:LLM4Drive: A Survey of Large Language Models for Autonomous Driving
地址:LLM4Drive: A Survey of Large Language Models for Autonomous Driving 摘要翻译 自动驾驶技术作为推动交通和城市出行变革的催化剂,正从基于规则的系统向数据驱动策略转变。传统的模块化系统受限于级联模块间的累积误差和缺乏灵活性的预设规则。…...
Python 训练营打卡 Day 47
注意力热力图可视化 在day 46代码的基础上,对比不同卷积层热力图可视化的结果 import torch import torch.nn as nn import torch.optim as optim from torchvision import datasets, transforms from torch.utils.data import DataLoader import matplotlib.pypl…...

篇章二 论坛系统——系统设计
目录 2.系统设计 2.1 技术选型 2.2 设计数据库结构 2.2.1 数据库实体 1. 数据库设计 1.1 数据库名: forum db 1.2 表的设计 1.3 编写SQL 2.系统设计 2.1 技术选型 2.2 设计数据库结构 2.2.1 数据库实体 通过需求分析获得概念类并结合业务实现过程中的技术需要&#x…...
CppCon 2015 学习:Time Programming Fundamentals
Civil Time 公历时间 特点: 共 6 个字段: Year(年)Month(月)Day(日)Hour(小时)Minute(分钟)Second(秒) 表示…...