liteflow有关于事务的问题

我爱海鲸 2025-09-06 20:45:58 暂无标签

简介事务、脚本节点

总结:

1. **声明式事务**在LiteFlow脚本组件中的行为依赖于外层方法的事务上下文
2. **编程式事务**在LiteFlow脚本组件中更加可靠,能够独立管理事务
3. 建议在LiteFlow脚本组件中使用编程式事务来确保事务的正确性
4. 如果使用声明式事务,需要确保调用方方法有`@Transactional`注解(这个注解在脚本中没有什么作用)

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);
                         }
                     });
                 }
             }
            """;

这里是事务是有发生回滚的,也就是说注解式事务和编程式事务,在没有事务的情况下调用脚本组件,只有编程式事务会发生回滚。

 

 

你好:我的2025