持久感知的KieSession在事务期间不使用悲观锁 [英] Persistent aware KieSession not using Pessimistic Lock during transactions
问题描述
我在 Spring Boot 2.3中使用了 Drools ,并且实现了持久感知的 KieSession
,其中 MySQL 用于存储会话.我已经成功地将Spring Boot的默认 EntityManagerFactory
与Drools集成在一起,但是我的问题是事务.默认情况下,Drools在交易过程中使用乐观锁,但是它允许我们也使用悲观锁,这正是我想要的.现在,在触发规则时,Drools使用以下查询在MySQL中保持/更新KieSession:
I am using Drools with Spring Boot 2.3 and I have implemented the persistent aware KieSession
, in which MySQL is used for storing the session. I have successfully integrated the default EntityManagerFactory
of Spring Boot with Drools but my problem is with transactions. By default, Drools uses Optimistic Lock during transactions but it allows us to use the Pessimistic Lock as well, which is what I want. Now while firing rules, Drools persists/updates the KieSession in MySQL with the following query:
update SessionInfo set lastModificationDate=?, rulesByteArray=?, startDate=?, OPTLOCK=? where id=? and OPTLOCK=?
现在,如果我不使用方法中使用 @Transactional
批注的事务,并且使用了 @Transactional
,则上面的语句将执行两次.触发规则后仅执行一次.
Now the above statement is executed twice if I do not use transactions using the @Transactional
annotation in the method, and if @Transactional
is used then the above statement is executed only once after firing the rules.
现在,如果我手动更改OPTLOCK字段的值,则Drools会引发异常:
Now, if I manually change the value of the OPTLOCK field then Drools throws an exception:
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.可以在此GitHub项目中查看整个堆栈跟踪.
I am unable to post the entire Stacktrace due to text length limitations here. The entire stacktrace can be viewed in this GitHub project.
我不确定Drools是否正在使用环境中定义的悲观锁.关于我的会话实现,我想拥有一个 KieSession
,因为我将KieSession用作 Bean
.
I am not sure whether Drools is using the Pessimistic Lock as defined in the environment. About my session implementation, I want to have a single KieSession
since I am using KieSession as a 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依赖项:
The Drools dependencies used:
<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项目中找到.任何帮助/建议将不胜感激.谢谢.
The code implementation can also be found in this GitHub Project. Any kind of help/suggestions will be much appreciated. Thank you.
推荐答案
Pessimistic locking is implemented only in JBPM see here
Drools持久性中没有此类功能, SessionInfo
将始终基于JPA的 @Version
批注使用OptimisticLocking.
There's no such functionality in Drools persistence, SessionInfo
will always use OptimisticLocking based on JPA's @Version
annotation.
如果您需要这样的功能,请在Drools的 Jira 中提出功能请求
If you need such feature, please file a feature request on Drools' Jira
这篇关于持久感知的KieSession在事务期间不使用悲观锁的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!