我在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项目中找到。任何帮助/建议都将不胜感激。谢谢您。
1条答案
按热度按时间x6h2sr281#
悲观锁只在jbpm中实现参见这里
drools持久性中没有这样的功能,
SessionInfo
将始终使用基于jpa的乐观锁定@Version
注解。如果你需要这样的功能,请在drools'jira上提交一个功能请求