总结:
LiteFlow官网: https://liteflow.cc/pages/71ff49/
搭建项目,参考:https://gitee.com/liu-haijin/liteflow-tra
调用service:
package com.example.liteflow.service;
import com.example.liteflow.constant.DynamicConstant;
import com.example.liteflow.entity.Interest;
import com.example.liteflow.entity.User;
import com.yomahub.liteflow.builder.LiteFlowNodeBuilder;
import com.yomahub.liteflow.builder.el.ELBus;
import com.yomahub.liteflow.builder.el.ELWrapper;
import com.yomahub.liteflow.builder.el.LiteFlowChainELBuilder;
import com.yomahub.liteflow.core.FlowExecutor;
import com.yomahub.liteflow.flow.LiteflowResponse;
import jakarta.annotation.Resource;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import java.time.LocalDateTime;
/**
* 2025/9/5.
*
* @author haijin
*/
@Service
@Slf4j
public class FlowService {
@Resource
private FlowExecutor flowExecutor;
@Resource
private UserService userService;
@Resource
private InterestService interestService;
@Transactional(rollbackFor = Exception.class)
public String exec() throws Exception {
ELWrapper el = ELBus.then("a");
User user = new User();
user.setName("test");
user.setAddress("深圳");
userService.save(user);
System.out.println(el.toEL(true));
LiteFlowChainELBuilder.createChain().setChainId("t123").setEL(
// 输出el表达式
el.toEL()
).build();
//构建一个普通脚本组件
LiteFlowNodeBuilder.createScriptNode().setId("a")
.setName("组件A")
.setScript(DynamicConstant.TEST_1)
.build();
LiteflowResponse liteflowResponse = flowExecutor.execute2Resp("t123", null, null);
if (!liteflowResponse.isSuccess()) {
throw liteflowResponse.getCause();
}
Interest interest = new Interest();
interest.setName("游泳");
interest.setCreateTime(LocalDateTime.now());
interestService.saveInterest(interest);
return "ok";
}
}
兴趣service:
package com.example.liteflow.service.impl;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.example.liteflow.entity.Interest;
import com.example.liteflow.mapper.InterestMapper;
import com.example.liteflow.service.InterestService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import java.time.LocalDateTime;
/**
* 兴趣服务实现类
*
* @author haijin
* @since 2024-01-01
*/
@Slf4j
@Service
public class InterestServiceImpl extends ServiceImpl<InterestMapper, Interest> implements InterestService {
@Transactional(rollbackFor = Exception.class)
@Override
public void saveInterest(Interest interest) {
this.save(interest);
// int i = 1 / 0;
}
}
脚本组件:
测试1:
/**
* 声明式事务,不保存数据,正常
*/
String TEST_1 = """
import com.yomahub.liteflow.core.NodeComponent;
import com.yomahub.liteflow.spi.holder.ContextAwareHolder;
import com.example.liteflow.entity.User;
import com.example.liteflow.service.UserService;
import org.springframework.transaction.annotation.Transactional;
public class Demo extends NodeComponent {
@Transactional(rollbackFor = Exception.class)
@Override
public void process() throws Exception {
System.out.println("Hello");
}
}
""";
数据插入也是成功的。
测试2:
/**
* 声明式事务,不保存数据,异常
*/
String TEST_1_3 = """
import com.yomahub.liteflow.core.NodeComponent;
import com.yomahub.liteflow.spi.holder.ContextAwareHolder;
import com.example.liteflow.entity.User;
import com.example.liteflow.service.UserService;
import org.springframework.transaction.annotation.Transactional;
public class Demo extends NodeComponent {
@Transactional(rollbackFor = Exception.class)
@Override
public void process() throws Exception {
System.out.println("Hello");
int i = 1/0;
}
}
""";
LiteflowResponse liteflowResponse = flowExecutor.execute2Resp("t123", null, null);
if (!liteflowResponse.isSuccess()) {
throw liteflowResponse.getCause();
}
这里如果报错就抛出异常了,所以事务也是有回滚的
测试3:
/**
* 声明式事务,保存数据,正常
*/
String TEST_1_1 = """
import com.yomahub.liteflow.core.NodeComponent;
import com.yomahub.liteflow.spi.holder.ContextAwareHolder;
import com.example.liteflow.entity.User;
import com.example.liteflow.service.UserService;
import org.springframework.transaction.annotation.Transactional;
public class Demo extends NodeComponent {
@Transactional(rollbackFor = Exception.class)
@Override
public void process() throws Exception {
UserService userService = ContextAwareHolder.loadContextAware().getBean(UserService.class);
User user = new User();
user.setName("test");
user.setAddress("广州");
userService.save(user);
System.out.println("Hello");
}
}
""";
插入数据也是成功的
测试4:
/**
* 声明式事务,保存数据,抛出异常
*/
String TEST_2 = """
import com.yomahub.liteflow.core.NodeComponent;
import com.yomahub.liteflow.spi.holder.ContextAwareHolder;
import com.example.liteflow.entity.User;
import com.example.liteflow.service.UserService;
import org.springframework.transaction.annotation.Transactional;
public class Demo extends NodeComponent throws Exception {
@Transactional(rollbackFor = Exception.class)
@Override
public void process() throws Exception {
UserService userService = ContextAwareHolder.loadContextAware().getBean(UserService.class);
User user = new User();
user.setName("test");
user.setAddress("广州");
userService.save(user);
int i = 1/0;
System.out.println("Hello");
}
}
""";
插入了数据,但是数据库中没有,事务此时是有效的。
测试5:
/**
* 声明式事务,保存数据,正常
*/
String TEST_1_1 = """
import com.yomahub.liteflow.core.NodeComponent;
import com.yomahub.liteflow.spi.holder.ContextAwareHolder;
import com.example.liteflow.entity.User;
import com.example.liteflow.service.UserService;
import org.springframework.transaction.annotation.Transactional;
public class Demo extends NodeComponent {
@Transactional(rollbackFor = Exception.class)
@Override
public void process() throws Exception {
UserService userService = ContextAwareHolder.loadContextAware().getBean(UserService.class);
User user = new User();
user.setName("test");
user.setAddress("广州");
userService.save(user);
System.out.println("Hello");
}
}
""";
现在我们在业务中重写一下逻辑:
package com.example.liteflow.service;
import com.example.liteflow.constant.DynamicConstant;
import com.example.liteflow.entity.Interest;
import com.example.liteflow.entity.User;
import com.yomahub.liteflow.builder.LiteFlowNodeBuilder;
import com.yomahub.liteflow.builder.el.ELBus;
import com.yomahub.liteflow.builder.el.ELWrapper;
import com.yomahub.liteflow.builder.el.LiteFlowChainELBuilder;
import com.yomahub.liteflow.core.FlowExecutor;
import com.yomahub.liteflow.flow.LiteflowResponse;
import jakarta.annotation.Resource;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import java.time.LocalDateTime;
/**
* 2025/9/5.
*
* @author haijin
*/
@Service
@Slf4j
public class FlowService {
@Resource
private FlowExecutor flowExecutor;
@Resource
private UserService userService;
@Resource
private InterestService interestService;
@Transactional(rollbackFor = Exception.class)
public String exec() throws Exception {
ELWrapper el = ELBus.then("a");
User user = new User();
user.setName("test");
user.setAddress("深圳");
userService.save(user);
System.out.println(el.toEL(true));
LiteFlowChainELBuilder.createChain().setChainId("t123").setEL(
// 输出el表达式
el.toEL()
).build();
//构建一个普通脚本组件
LiteFlowNodeBuilder.createScriptNode().setId("a")
.setName("组件A")
.setScript(DynamicConstant.TEST_1_1)
.build();
LiteflowResponse liteflowResponse = flowExecutor.execute2Resp("t123", null, null);
if (!liteflowResponse.isSuccess()) {
throw liteflowResponse.getCause();
}
int i = 1/0;
// Interest interest = new Interest();
// interest.setName("游泳");
// interest.setCreateTime(LocalDateTime.now());
//
// interestService.saveInterest(interest);
return "ok";
}
}
此时的事务也是生效的。
测试6
修改一下业务逻辑
还是TEST_1_1 组件
在兴趣业务中报错
事务也是有回滚的。如果脚本组件上不加@Transactional(rollbackFor = Exception.class),只要在调用组件的service方法上加入@Transactional(rollbackFor = Exception.class),数据也是能够回滚的,也就是说脚本组件上的这个注解是没有意义的
测试7:
package com.example.liteflow.service;
import com.example.liteflow.constant.DynamicConstant;
import com.example.liteflow.entity.Interest;
import com.example.liteflow.entity.User;
import com.example.liteflow.mapper.UserMapper;
import com.yomahub.liteflow.builder.LiteFlowNodeBuilder;
import com.yomahub.liteflow.builder.el.ELBus;
import com.yomahub.liteflow.builder.el.ELWrapper;
import com.yomahub.liteflow.builder.el.LiteFlowChainELBuilder;
import com.yomahub.liteflow.core.FlowExecutor;
import com.yomahub.liteflow.flow.LiteflowResponse;
import jakarta.annotation.Resource;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import java.time.LocalDateTime;
/**
* 2025/9/5.
*
* @author haijin
*/
@Service
@Slf4j
public class FlowService {
@Resource
private FlowExecutor flowExecutor;
@Resource
private UserService userService;
@Resource
private InterestService interestService;
// @Transactional(rollbackFor = Exception.class)
public String exec() throws Exception {
ELWrapper el = ELBus.then("a");
// User user = new User();
// user.setName("test");
// user.setAddress("深圳");
//
// userService.save(user);
System.out.println(el.toEL(true));
LiteFlowChainELBuilder.createChain().setChainId("t123").setEL(
// 输出el表达式
el.toEL()
).build();
//构建一个普通脚本组件
LiteFlowNodeBuilder.createScriptNode().setId("a")
.setName("组件A")
.setScript(DynamicConstant.TEST_2)
.build();
LiteflowResponse liteflowResponse = flowExecutor.execute2Resp("t123", null, null);
//
// if (!liteflowResponse.isSuccess()) {
// throw liteflowResponse.getCause();
// }
// int i = 1/0;
//
Interest interest = new Interest();
interest.setName("游泳");
interest.setCreateTime(LocalDateTime.now());
interestService.saveInterest(interest);
return "ok";
}
}
测试的脚本组件:
/**
* 声明式事务,保存数据,抛出异常
*/
String TEST_2 = """
import com.yomahub.liteflow.core.NodeComponent;
import com.yomahub.liteflow.spi.holder.ContextAwareHolder;
import com.example.liteflow.entity.User;
import com.example.liteflow.service.UserService;
import org.springframework.transaction.annotation.Transactional;
public class Demo extends NodeComponent {
@Transactional(rollbackFor = Exception.class)
@Override
public void process() throws Exception {
UserService userService = ContextAwareHolder.loadContextAware().getBean(UserService.class);
User user = new User();
user.setName("test");
user.setAddress("广州");
userService.save(user);
int i = 1/0;
System.out.println("Hello");
}
}
""";
Interest业务:
@Slf4j
@Service
public class InterestServiceImpl extends ServiceImpl<InterestMapper, Interest> implements InterestService {
@Transactional(rollbackFor = Exception.class)
@Override
public void saveInterest(Interest interest) {
this.save(interest);
int i = 1 / 0;
}
}
组件里的数据没法发生回滚,Interest业务里的数据发生了回滚。
测试8:
现在我们清空数据库的数据,使用编程式事务
/**
* 编程式事务,保存数据,异常
*/
String TEST_3_1 = """
import com.yomahub.liteflow.core.NodeComponent;
import com.yomahub.liteflow.spi.holder.ContextAwareHolder;
import com.example.liteflow.entity.User;
import com.example.liteflow.service.UserService;
import org.springframework.transaction.support.TransactionTemplate;
import org.springframework.transaction.TransactionStatus;
import org.springframework.transaction.support.DefaultTransactionDefinition;
public class Demo extends NodeComponent {
@Override
public void process() throws Exception {
// 获取 UserService 和 TransactionTemplate
UserService userService = ContextAwareHolder.loadContextAware().getBean(UserService.class);
TransactionTemplate transactionTemplate = ContextAwareHolder.loadContextAware().getBean(TransactionTemplate.class);
// 使用编程式事务执行操作
transactionTemplate.execute(status -> {
try {
User user = new User();
user.setName("test");
user.setAddress("广州");
userService.save(user);
int i = 1/0; // 这里会抛出异常,触发回滚
System.out.println("Hello");
return null; // 执行成功返回null
} catch (Exception e) {
// 设置回滚标志
status.setRollbackOnly();
throw new RuntimeException("事务执行失败,已回滚", e);
}
});
}
}
""";
两个表的数据都发生了回滚。
测试9:
如果Interest业务没有报错呢?
@Slf4j
@Service
public class InterestServiceImpl extends ServiceImpl<InterestMapper, Interest> implements InterestService {
@Transactional(rollbackFor = Exception.class)
@Override
public void saveInterest(Interest interest) {
this.save(interest);
// int i = 1 / 0;
}
}
脚本组件里的数据是有发生回滚的,Interest业务没有发生回滚,其实是这两个事务是独立的事务
测试10:
现在使用正常的编程式事务:
/**
* 编程式事务,保存数据,正常
*/
String TEST_3 = """
import com.yomahub.liteflow.core.NodeComponent;
import com.yomahub.liteflow.spi.holder.ContextAwareHolder;
import com.example.liteflow.entity.User;
import com.example.liteflow.service.UserService;
import org.springframework.transaction.support.TransactionTemplate;
import org.springframework.transaction.TransactionStatus;
import org.springframework.transaction.support.DefaultTransactionDefinition;
public class Demo extends NodeComponent {
@Override
public void process() throws Exception {
// 获取 UserService 和 TransactionTemplate
UserService userService = ContextAwareHolder.loadContextAware().getBean(UserService.class);
TransactionTemplate transactionTemplate = ContextAwareHolder.loadContextAware().getBean(TransactionTemplate.class);
// 使用编程式事务执行操作
transactionTemplate.execute(status -> {
try {
User user = new User();
user.setName("test");
user.setAddress("广州");
userService.save(user);
// int i = 1/0; // 这里会抛出异常,触发回滚
System.out.println("Hello");
return null; // 执行成功返回null
} catch (Exception e) {
// 设置回滚标志
status.setRollbackOnly();
throw new RuntimeException("事务执行失败,已回滚", e);
}
});
}
}
""";
在Interest业务中进行报错
@Slf4j
@Service
public class InterestServiceImpl extends ServiceImpl<InterestMapper, Interest> implements InterestService {
@Transactional(rollbackFor = Exception.class)
@Override
public void saveInterest(Interest interest) {
this.save(interest);
int i = 1 / 0;
}
}
两个数据都是发生了回滚的,说明编程式事务就没有问题的
其实调用的重点是在调用的的业务方法中添加事务注解
测试11:
现在在来对比一下注解式事务,我们不加事务的注解到调用的方法中,只调用组件的报错的插入数据
/**
* 声明式事务,保存数据,抛出异常
*/
String TEST_2 = """
import com.yomahub.liteflow.core.NodeComponent;
import com.yomahub.liteflow.spi.holder.ContextAwareHolder;
import com.example.liteflow.entity.User;
import com.example.liteflow.service.UserService;
import org.springframework.transaction.annotation.Transactional;
public class Demo extends NodeComponent {
@Transactional(rollbackFor = Exception.class)
@Override
public void process() throws Exception {
UserService userService = ContextAwareHolder.loadContextAware().getBean(UserService.class);
User user = new User();
user.setName("test");
user.setAddress("广州");
userService.save(user);
int i = 1/0;
System.out.println("Hello");
}
}
""";
调用的业务:
package com.example.liteflow.service;
import com.example.liteflow.constant.DynamicConstant;
import com.example.liteflow.entity.Interest;
import com.example.liteflow.entity.User;
import com.example.liteflow.mapper.UserMapper;
import com.yomahub.liteflow.builder.LiteFlowNodeBuilder;
import com.yomahub.liteflow.builder.el.ELBus;
import com.yomahub.liteflow.builder.el.ELWrapper;
import com.yomahub.liteflow.builder.el.LiteFlowChainELBuilder;
import com.yomahub.liteflow.core.FlowExecutor;
import com.yomahub.liteflow.flow.LiteflowResponse;
import jakarta.annotation.Resource;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import java.time.LocalDateTime;
/**
* 2025/9/5.
*
* @author haijin
*/
@Service
@Slf4j
public class FlowService {
@Resource
private FlowExecutor flowExecutor;
@Resource
private UserService userService;
@Resource
private InterestService interestService;
// @Transactional(rollbackFor = Exception.class)
public String exec() throws Exception {
ELWrapper el = ELBus.then("a");
// User user = new User();
// user.setName("test");
// user.setAddress("深圳");
//
// userService.save(user);
System.out.println(el.toEL(true));
LiteFlowChainELBuilder.createChain().setChainId("t123").setEL(
// 输出el表达式
el.toEL()
).build();
//构建一个普通脚本组件
LiteFlowNodeBuilder.createScriptNode().setId("a")
.setName("组件A")
.setScript(DynamicConstant.TEST_2)
.build();
LiteflowResponse liteflowResponse = flowExecutor.execute2Resp("t123", null, null);
//
// if (!liteflowResponse.isSuccess()) {
// throw liteflowResponse.getCause();
// }
// int i = 1/0;
//
// Interest interest = new Interest();
// interest.setName("游泳");
// interest.setCreateTime(LocalDateTime.now());
//
// interestService.saveInterest(interest);
return "ok";
}
}
数据不能够进行回滚
但如果换成编程式事务
/**
* 编程式事务,保存数据,异常
*/
String TEST_3_1 = """
import com.yomahub.liteflow.core.NodeComponent;
import com.yomahub.liteflow.spi.holder.ContextAwareHolder;
import com.example.liteflow.entity.User;
import com.example.liteflow.service.UserService;
import org.springframework.transaction.support.TransactionTemplate;
import org.springframework.transaction.TransactionStatus;
import org.springframework.transaction.support.DefaultTransactionDefinition;
public class Demo extends NodeComponent {
@Override
public void process() throws Exception {
// 获取 UserService 和 TransactionTemplate
UserService userService = ContextAwareHolder.loadContextAware().getBean(UserService.class);
TransactionTemplate transactionTemplate = ContextAwareHolder.loadContextAware().getBean(TransactionTemplate.class);
// 使用编程式事务执行操作
transactionTemplate.execute(status -> {
try {
User user = new User();
user.setName("test");
user.setAddress("广州");
userService.save(user);
int i = 1/0; // 这里会抛出异常,触发回滚
System.out.println("Hello");
return null; // 执行成功返回null
} catch (Exception e) {
// 设置回滚标志
status.setRollbackOnly();
throw new RuntimeException("事务执行失败,已回滚", e);
}
});
}
}
""";
这里是事务是有发生回滚的,也就是说注解式事务和编程式事务,在没有事务的情况下调用脚本组件,只有编程式事务会发生回滚。