事务的特性
事务有以下四个特性,通常称为ACID:
-
原子性(Atomicity): 事务是一个不可分割的基本工作单位,在事务执行过程中,要么全部执行成功,要么全部失败回滚。
-
一致性(Consistency): 在事务开始之前和事务结束之后,数据库的完整性约束没有被破坏。在事务执行过程中,数据库总是从一个一致性状态转移到另一个一致性状态。
-
隔离性(Isolation): 对于任何两个并发事务,在系统中的操作好像是顺序执行的,其中一个操作的结果不受另一个操作的影响。
-
持久性(Durability): 一旦提交事务,对数据所做的更改就会永久保存到数据库中,即使系统发生故障,这些更改也应该得以保存。
这些特性确保了数据库事务的可靠性和一致性,也是数据库管理系统(DBMS)的重要功能之一。
开启事务的方式
在基于Spring框架的应用中,可以通过以下几种方式来开启事务
- 使用注解方式:通过在方法上添加
@Transactional
注解来启用事务。可以将@Transactional
注解添加在类级别上,表示该类的所有方法都被视为事务性操作,也可以只在特定的方法上添加注解,表示该方法是一个事务性操作。@Transactional public class ExampleService {public void doSomething() {// 事务性操作} }
- 使用XML配置方式:通过在Spring的配置文件中声明
<tx:annotation-driven />
来启用注解驱动的事务管理,并使用<tx:advice>
和<aop:config>
元素配置事务增强。<beans xmlns:tx="http://www.springframework.org/schema/tx" xmlns:aop="http://www.springframework.org/schema/aop"><tx:annotation-driven /><bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager"><property name="dataSource" ref="dataSource" /></bean><!-- 声明事务增强 --><tx:advice id="txAdvice" transaction-manager="transactionManager"><tx:attributes><tx:method name="*" propagation="REQUIRED" /></tx:attributes></tx:advice><!-- 配置事务切面 --><aop:config><aop:advisor advice-ref="txAdvice" pointcut="execution(* com.example.service.*.*(..))" /></aop:config></beans>
- 通过Spring提供的
TransactionTemplate
或PlatformTransactionManager
来创建事务。 -
.//使用TransactionTemplate @Autowired private PlatformTransactionManager transactionManager;public void performTransactionalOperation() {TransactionTemplate transactionTemplate = new TransactionTemplate(transactionManager);transactionTemplate.execute(new TransactionCallback<Void>() {@Overridepublic Void doInTransaction(TransactionStatus status) {try {// 在这里执行事务操作,如数据库的增删改操作等} catch (Exception ex) {status.setRollbackOnly(); // 如果出现异常,设置回滚事务throw ex;}return null;}}); } //使用PlatformTransactionManager @Autowired private PlatformTransactionManager transactionManager;public void performTransactionalOperation() {TransactionDefinition transactionDefinition = new DefaultTransactionDefinition();TransactionStatus status = transactionManager.getTransaction(transactionDefinition);try {// 在这里执行事务操作,如数据库的增删改操作等transactionManager.commit(status); // 如果没有异常,提交事务} catch (Exception ex) {transactionManager.rollback(status); // 如果出现异常,回滚事务throw ex;} }
这些方式都基于Spring事务管理器的能力来创建和管理事务。注意,在使用事务期间,应该遵循正确的异常处理和事务提交/回滚的方式,以确保事务的完整性和一致性。
使用事务的基本流程
-
开始事务。在执行任何数据库操作之前,应该通过命令或API来显式地开始一个新的事务。
-
执行数据库操作。在事务中,可以执行多个增删改查等数据库操作语句,以及开发人员自己的代码逻辑,这些操作会被当做一个整体来处理。
-
提交事务或回滚事务。当所有的操作都执行成功,没有发生任何错误或异常时,应该通过命令或API显式地提交事务;如果其中任何一个操作失败或出现异常,则应该回滚整个事务,使得所有操作都不会造成任何影响。
-
结束事务。在提交或回滚事务之后,需要通过命令或API来显式地结束该事务。
需要注意的是,在多数编程语言和数据库中,事务必须在同一个数据库连接上使用,以确保事务中的所有操作都在同一会话下被处理。另外,当使用事务时,应该避免过长的事务处理时间,因为这会影响数据库的并发性能。
事务的嵌套使用
事务的嵌套使用是指在一个事务的执行过程中,调用了另一个需要事务的方法。在Spring框架中,可以使用Propagation
属性来控制事务的传播行为。
在Spring中,Propagation
属性有不同的取值,常用的包括:
Propagation.REQUIRED
:如果当前存在事务,则加入该事务;如果当前没有事务,则新建一个事务。Propagation.REQUIRES_NEW
:无论当前是否存在事务,都新建一个事务,并将当前事务挂起。Propagation.NESTED
:如果当前存在事务,则在一个嵌套事务中执行;如果当前没有事务,则行为类似于Propagation.REQUIRED
。
首先,确保你的代码中已经开启了事务。可以通过在方法上添加@Transactional
注解来实现。
然后,在需要嵌套事务的方法中,使用不同的Propagation
属性值来指定事务的传播行为。
@Service
@Transactional
public class TransactionalService {@Autowiredprivate PlatformTransactionManager transactionManager;public void outerMethod() {// 在外部方法中执行一些操作innerMethod();}@Transactional(propagation = Propagation.REQUIRES_NEW)public void innerMethod() {// 在内部方法中执行一些需要独立事务的操作}
}
在上面的示例中,outerMethod
方法使用默认的事务传播行为Propagation.REQUIRED
,而innerMethod
方法使用Propagation.REQUIRES_NEW
,表示需要一个新的独立事务。如果outerMethod
方法运行在一个已存在的事务中,那么innerMethod
方法将会新建一个独立的嵌套事务。
注意,嵌套事务的实现是依赖于底层数据库的支持,例如MySQL InnoDB引擎支持嵌套事务,而MyISAM引擎不支持。因此,确保你使用的数据库引擎支持嵌套事务,并且你的事务管理器和数据库配置正确。
事务关闭
事务的关闭是指事务执行完毕或者发生异常时,需要显式地进行事务的提交或回滚操作,以确保事务的完整性和一致性。
在Spring框架中,事务的关闭可以通过事务管理器的方法来实现。
@Autowired
private PlatformTransactionManager transactionManager;public void rollbackTransaction() {TransactionStatus status = transactionManager.getTransaction(new DefaultTransactionDefinition());try {// 在事务中执行操作transactionManager.commit(status); // 提交事务} catch (Exception e) {transactionManager.rollback(status); // 回滚事务}
}
需要注意的是,事务的关闭操作应该放在合适的地方,例如在业务方法的最后一步进行关闭。如果事务管理器配置了自动提交事务(@Transactional
注解的autoCommit
属性为true),则在方法结束时会自动进行事务的提交或回滚,无需手动关闭事务。