持久感知 KieSession 在事务期间不使用悲观锁
Persistent aware KieSession not using Pessimistic Lock during transactions
我正在使用 Drools 和 Spring Boot 2.3,我已经实现了持久感知 KieSession
,其中MySQL用于存储session。我已经成功地将 Spring Boot 的默认值 EntityManagerFactory
与 Drools 集成,但我的问题是交易。默认情况下,Drools 在事务期间使用乐观锁,但它也允许我们使用悲观锁,这正是我想要的。现在,在触发规则时,Drools persists/updates MySQL 中的 KieSession 使用以下查询:
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]
由于此处的文本长度限制,我无法 post 整个 Stacktrace。整个堆栈跟踪可以在 this GitHub project.
中查看
我不确定 Drools 是否在使用环境中定义的悲观锁。关于我的会话实现,我想要一个 KieSession
因为我使用 KieSession 作为 Bean
.
下面是我的实现:
配置class:
@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;
}
}
控制器class:
@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();
}
}
事实class
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> {
}
服务class:
@Service
public class PersistentSessionDAO {
@Autowired
private DroolsSessionRepository droolsSessionRepository;
public List<SessionInfo> getSessionDetails() {
return droolsSessionRepository.findAll();
}
}
亚军class:
@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>
代码实现也可以在this GitHub Project中找到。任何形式的 help/suggestions 都将不胜感激。谢谢。
我正在使用 Drools 和 Spring Boot 2.3,我已经实现了持久感知 KieSession
,其中MySQL用于存储session。我已经成功地将 Spring Boot 的默认值 EntityManagerFactory
与 Drools 集成,但我的问题是交易。默认情况下,Drools 在事务期间使用乐观锁,但它也允许我们使用悲观锁,这正是我想要的。现在,在触发规则时,Drools persists/updates MySQL 中的 KieSession 使用以下查询:
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]
由于此处的文本长度限制,我无法 post 整个 Stacktrace。整个堆栈跟踪可以在 this GitHub project.
中查看我不确定 Drools 是否在使用环境中定义的悲观锁。关于我的会话实现,我想要一个 KieSession
因为我使用 KieSession 作为 Bean
.
下面是我的实现:
配置class:
@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;
}
}
控制器class:
@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();
}
}
事实class
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> {
}
服务class:
@Service
public class PersistentSessionDAO {
@Autowired
private DroolsSessionRepository droolsSessionRepository;
public List<SessionInfo> getSessionDetails() {
return droolsSessionRepository.findAll();
}
}
亚军class:
@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>
代码实现也可以在this GitHub Project中找到。任何形式的 help/suggestions 都将不胜感激。谢谢。