1. 简介
编程式事务管理是通过编写代码来管理事务,相对于声明式事务(@transactional注解),它提供了更细粒度的事务控制。在 springboot 中,主要有两种实现方式:
- 使用 transactiontemplate
- 直接使用 transactionmanager
2. transactiontemplate 方式
transactiontemplate 是最简单的编程式事务实现方式,它对底层事务 api 进行了封装,使用起来更加便捷。
2.1 基本配置
@configuration
public class transactionconfig {
@autowired
private platformtransactionmanager transactionmanager;
@bean
public transactiontemplate transactiontemplate() {
transactiontemplate template = new transactiontemplate();
template.settransactionmanager(transactionmanager);
// 设置默认的事务传播行为
template.setpropagationbehavior(transactiondefinition.propagation_required);
// 设置默认的事务隔离级别
template.setisolationlevel(transactiondefinition.isolation_default);
// 设置默认超时时间
template.settimeout(30);
return template;
}
}2.2 基本使用示例
@service
@slf4j
public class userservice {
@autowired
private transactiontemplate transactiontemplate;
@autowired
private userrepository userrepository;
public user createuser(user user) {
// 使用 execute 方法执行有返回值的事务操作
return transactiontemplate.execute(status -> {
try {
user saveduser = userrepository.save(user);
// 模拟其他操作
updateuserprofile(saveduser);
return saveduser;
} catch (exception e) {
// 手动标记事务回滚
status.setrollbackonly();
log.error("创建用户失败", e);
throw new runtimeexception("创建用户失败", e);
}
});
}
public void batchcreateusers(list<user> users) {
// 使用 executewithoutresult 方法执行无返回值的事务操作
transactiontemplate.executewithoutresult(status -> {
try {
for (user user : users) {
userrepository.save(user);
}
} catch (exception e) {
status.setrollbackonly();
log.error("批量创建用户失败", e);
throw new runtimeexception("批量创建用户失败", e);
}
});
}
}3. transactionmanager 方式
直接使用 transactionmanager 提供了更细粒度的事务控制,但使用起来相对复杂。
3.1 基本使用示例
@service
@slf4j
public class orderservice {
@autowired
private platformtransactionmanager transactionmanager;
@autowired
private orderrepository orderrepository;
public order createorder(order order) {
// 定义事务属性
defaulttransactiondefinition def = new defaulttransactiondefinition();
def.setpropagationbehavior(transactiondefinition.propagation_required);
def.setisolationlevel(transactiondefinition.isolation_read_committed);
def.settimeout(30);
// 获取事务状态
transactionstatus status = transactionmanager.gettransaction(def);
try {
// 执行业务逻辑
order savedorder = orderrepository.save(order);
// 处理订单相关的其他操作
processorderdetails(savedorder);
// 提交事务
transactionmanager.commit(status);
return savedorder;
} catch (exception e) {
// 回滚事务
transactionmanager.rollback(status);
log.error("创建订单失败", e);
throw new runtimeexception("创建订单失败", e);
}
}
}3.2 嵌套事务示例
@service
@slf4j
public class paymentservice {
@autowired
private platformtransactionmanager transactionmanager;
@autowired
private paymentrepository paymentrepository;
public void processpayment(payment payment) {
// 外部事务定义
defaulttransactiondefinition outerdef = new defaulttransactiondefinition();
outerdef.setpropagationbehavior(transactiondefinition.propagation_required);
transactionstatus outerstatus = transactionmanager.gettransaction(outerdef);
try {
// 外部事务操作
paymentrepository.save(payment);
// 内部事务定义
defaulttransactiondefinition innerdef = new defaulttransactiondefinition();
innerdef.setpropagationbehavior(transactiondefinition.propagation_nested);
transactionstatus innerstatus = transactionmanager.gettransaction(innerdef);
try {
// 执行内部事务操作
processpaymentdetails(payment);
transactionmanager.commit(innerstatus);
} catch (exception e) {
// 回滚内部事务
transactionmanager.rollback(innerstatus);
log.error("支付详情处理失败", e);
throw e;
}
// 提交外部事务
transactionmanager.commit(outerstatus);
} catch (exception e) {
// 回滚外部事务
transactionmanager.rollback(outerstatus);
log.error("支付处理失败", e);
throw new runtimeexception("支付处理失败", e);
}
}
}4. 事务传播行为
在编程式事务中,我们可以精确控制事务的传播行为:
@service
public class transactionpropagationexample {
@autowired
private transactiontemplate transactiontemplate;
public void demonstratepropagation() {
// required 传播行为
transactiontemplate requiredtemplate = new transactiontemplate(transactiontemplate);
requiredtemplate.setpropagationbehavior(transactiondefinition.propagation_required);
// requires_new 传播行为
transactiontemplate requiresnewtemplate = new transactiontemplate(transactiontemplate);
requiresnewtemplate.setpropagationbehavior(transactiondefinition.propagation_requires_new);
// 嵌套使用不同的传播行为
requiredtemplate.execute(outerstatus -> {
// 外部事务逻辑
requiresnewtemplate.execute(innerstatus -> {
// 内部事务逻辑(新的事务)
return null;
});
return null;
});
}
}5. 事务隔离级别
示例展示如何设置不同的事务隔离级别:
@service
public class transactionisolationexample {
@autowired
private platformtransactionmanager transactionmanager;
public void demonstrateisolation() {
// 读已提交隔离级别
defaulttransactiondefinition readcommitteddef = new defaulttransactiondefinition();
readcommitteddef.setisolationlevel(transactiondefinition.isolation_read_committed);
transactionstatus readcommittedstatus = transactionmanager.gettransaction(readcommitteddef);
try {
// 业务逻辑
transactionmanager.commit(readcommittedstatus);
} catch (exception e) {
transactionmanager.rollback(readcommittedstatus);
throw e;
}
// 可重复读隔离级别
defaulttransactiondefinition repeatablereaddef = new defaulttransactiondefinition();
repeatablereaddef.setisolationlevel(transactiondefinition.isolation_repeatable_read);
// ... 类似的事务处理逻辑
}
}6. 最佳实践
6.1 事务模板封装
创建一个通用的事务处理模板:
@component
@slf4j
public class transactionhelper {
@autowired
private transactiontemplate transactiontemplate;
public <t> t executeintransaction(transactioncallback<t> action) {
try {
return transactiontemplate.execute(action);
} catch (exception e) {
log.error("事务执行失败", e);
throw new runtimeexception("事务执行失败", e);
}
}
public void executeintransactionwithoutresult(consumer<transactionstatus> action) {
try {
transactiontemplate.executewithoutresult(action);
} catch (exception e) {
log.error("事务执行失败", e);
throw new runtimeexception("事务执行失败", e);
}
}
}
// 使用示例
@service
public class businessservice {
@autowired
private transactionhelper transactionhelper;
public void dobusiness() {
transactionhelper.executeintransactionwithoutresult(status -> {
// 业务逻辑
});
}
}7. 常见问题与解决方案
7.1 事务超时处理
@service
public class timeoutexample {
@autowired
private transactiontemplate transactiontemplate;
public void handletimeout() {
transactiontemplate timeouttemplate = new transactiontemplate(transactiontemplate);
timeouttemplate.settimeout(5); // 设置5秒超时
try {
timeouttemplate.execute(status -> {
// 可能超时的业务逻辑
return null;
});
} catch (transactiontimedoutexception e) {
// 处理超时异常
log.error("事务执行超时", e);
throw new runtimeexception("事务执行超时", e);
}
}
}7.2 异常处理最佳实践
@service
public class exceptionhandlingexample {
@autowired
private transactiontemplate transactiontemplate;
public void handleexceptions() {
try {
transactiontemplate.execute(status -> {
try {
// 业务逻辑
return null;
} catch (businessexception e) {
// 业务异常,标记回滚
status.setrollbackonly();
throw e;
} catch (exception e) {
// 其他异常,标记回滚
status.setrollbackonly();
throw new runtimeexception("未预期的错误", e);
}
});
} catch (exception e) {
// 统一异常处理
handleexception(e);
}
}
private void handleexception(exception e) {
if (e instanceof businessexception) {
// 处理业务异常
log.warn("业务异常: {}", e.getmessage());
} else {
// 处理系统异常
log.error("系统异常", e);
}
throw e;
}
}虽然编程式事务提供了更细粒度的控制,但在大多数情况下,声明式事务(@transactional)可能是更好的选择。只有在需要特别精细的事务控制时,才考虑使用编程式事务。
到此这篇关于springboot 编程式事务使用的文章就介绍到这了,更多相关springboot 编程式事务内容请搜索代码网以前的文章或继续浏览下面的相关文章希望大家以后多多支持代码网!
发表评论