spring持久会话在事务期间不使用悲观锁

yrwegjxp  于 2021-07-13  发布在  Java
关注(0)|答案(1)|浏览(335)

我在springboot2.3中使用drools,并且实现了持久感知 KieSession ,其中mysql用于存储会话。我已成功集成默认 EntityManagerFactory 但我的问题是事务。默认情况下,drools在事务期间使用乐观锁,但它也允许我们使用悲观锁,这正是我想要的。现在,当触发规则时,drools会使用以下查询来保持/更新mysql中的会话:

update SessionInfo set lastModificationDate=?, rulesByteArray=?, startDate=?, OPTLOCK=? where id=? and OPTLOCK=?

现在,如果我不使用 @Transactional 方法中的注解,如果 @Transactional 则上述语句仅在触发规则后执行一次。
现在,如果手动更改optlock字段的值,drools会抛出一个异常:

javax.persistence.OptimisticLockException: Row was updated or deleted by another transaction (or unsaved-value mapping was incorrect) : [org.drools.persistence.info.SessionInfo#1]

然后:

Caused by: org.hibernate.StaleObjectStateException: Row was updated or deleted by another transaction (or unsaved-value mapping was incorrect) : [org.drools.persistence.info.SessionInfo#1]

由于这里的文本长度限制,我无法发布整个stacktrace。整个stacktrace可以在这个github项目中查看。
我不确定drools是否使用了环境中定义的悲观锁。关于我的会话实现,我想有一个 KieSession 因为我把kiesession当作 Bean .
以下是我的实现:
配置类:

@Configuration
public class DynamicDroolsConfig {

    private KieServices kieServices;
    private KieFileSystem kieFileSystem;

    @Autowired
    private PersistentSessionDAO persistentSessionDAO;
    @PersistenceUnit
    private EntityManagerFactory entityManagerFactory;
    @Autowired
    private PlatformTransactionManager platformTransactionManager;

    @PostConstruct
    private void init() {
        this.kieServices = KieServices.Factory.get();
        this.kieFileSystem = kieServices.newKieFileSystem();
    }

    @Bean
    public KieServices getKieServices() {
        return this.kieServices;
    }

    @Bean
    public KieContainer getKieContainer() {
        kieFileSystem.write(ResourceFactory.newClassPathResource("rules/rules.drl"));
        final KieRepository kieRepository = kieServices.getRepository();
        kieRepository.addKieModule(kieRepository::getDefaultReleaseId);
        KieBuilder kb = kieServices.newKieBuilder(kieFileSystem).buildAll();
        KieModule kieModule = kb.getKieModule();
        return kieServices.newKieContainer(kieModule.getReleaseId());
    }

    @Bean
    public KieFileSystem getFileSystem() {
        return kieFileSystem;
    }

    @Bean
    public KieSession kieSession() {
        List<SessionInfo> sessionDetails = persistentSessionDAO.getSessionDetails();

        if (sessionDetails.size() == 0) {
            return kieServices.getStoreServices().newKieSession(getKieContainer().getKieBase(), null, getEnv());
        } else {
            return kieServices.getStoreServices().loadKieSession(sessionDetails.get(0).getId(), getKieContainer().getKieBase(), null, getEnv());
        }
    }

    private Environment getEnv() {
        Environment env = kieServices.newEnvironment();
        env.set(EnvironmentName.ENTITY_MANAGER_FACTORY, entityManagerFactory);
        env.set(EnvironmentName.TRANSACTION_MANAGER, platformTransactionManager);
        env.set(EnvironmentName.USE_PESSIMISTIC_LOCKING, true);
        env.set(EnvironmentName.USE_PESSIMISTIC_LOCKING_MODE, LockModeType.PESSIMISTIC_FORCE_INCREMENT.name());
        return env;
    }
}

控制器类:

@RestController
public class MyController {

    @Autowired
    private KieSession kieSession;

    @Transactional
    @GetMapping("fire-person")
    public void firePerson() {
        Person person = new Person();
        person.setName("Christy");
        kieSession.insert(person);
        kieSession.fireAllRules();
    }
}

事实类

public class Person implements Serializable {

    private String name;
    private int age;
    private String gender;
    private String toCompareName;
    private String toCompareGender;

    // getters and setters
}

存储库界面:

public interface DroolsSessionRepository extends JpaRepository<SessionInfo, Long> {
}

服务级别:

@Service
public class PersistentSessionDAO {

    @Autowired
    private DroolsSessionRepository droolsSessionRepository;

    public List<SessionInfo> getSessionDetails() {
        return droolsSessionRepository.findAll();
    }
}

跑步者课程:

@EntityScan(basePackages = {"com.sam.springdroolspersistence.entity", "org.drools.persistence.info"})
@EnableJpaRepositories
@SpringBootApplication
public class SpringDroolsPersistenceApplication {

    public static void main(String[] args) {
        SpringApplication.run(SpringDroolsPersistenceApplication.class, args);
    }
}

使用的drools依赖项:

<dependency>
            <groupId>org.drools</groupId>
            <artifactId>drools-persistence-jpa</artifactId>
            <version>${drools-version}</version>
        </dependency>

        <dependency>
            <groupId>org.kie</groupId>
            <artifactId>kie-spring</artifactId>
            <version>${drools-version}</version>
        </dependency>

        <dependency>
            <groupId>org.jbpm</groupId>
            <artifactId>jbpm-persistence-jpa</artifactId>
            <version>${drools-version}</version>
        </dependency>

代码实现也可以在这个github项目中找到。任何帮助/建议都将不胜感激。谢谢您。

x6h2sr28

x6h2sr281#

悲观锁只在jbpm中实现参见这里
drools持久性中没有这样的功能, SessionInfo 将始终使用基于jpa的乐观锁定 @Version 注解。
如果你需要这样的功能,请在drools'jira上提交一个功能请求

相关问题