春季状态机与JPA持久化-存储库用法

huangapple go评论73阅读模式
英文:

Spring state machine with JPA persistence- Repository usage

问题

我正在尝试弄清楚如何轻松使用Spring状态机,包括与JPA的持久化。

这是我正在处理的问题:

不兼容的数据类型 - 工厂和持久化

在程序的某个特定点,我想要使用与用户连接的状态机。为此有相关的存储库(项目 spring-statemachine-data-jpa)。首先,要检查是否已经为玩家创建了状态机,可以使用该存储库。如果没有,就需要创建一个新的状态机并将其持久化。

问题在于我有不同类型的状态机。工厂创建了一个 StateMachine<UserState, UserEvent>,而存储库返回一个 JpaRepositoryStateMachine。它们之间不兼容,对于我来说不清楚如何持久化/创建/恢复这些状态机。

您能为我澄清一下吗?

@Autowired
private StateMachineRepository<JpaRepositoryStateMachine> repository;

public someMethod(User user) {

Optional<JpaRepositoryStateMachine> stateMachine = repository.findById(user.getId()); // JPA状态机

if(stateMachine.isEmpty()) {
            StateMachine<UserState, UserEvent> createdStateMachine = factory.getStateMachine(user.getId()); // Spring状态机
            repository.save(createdStateMachine); // 编译错误
        }

// 在这里:已准备好使用的状态机 - 如何操作?

}

谢谢您的帮助!

英文:

I am trying to figure out how to easily use spring state machine including persistence with JPA.
This is the problem I am dealing with:

Incompatible data types - factory and persistence

At a certain point in the program I would like to use the state machine which is connected to a user. There are repositories for that purpose (project spring-statemachine-data-jpa).
At first there is a check if a state machine already exists for a player, using the repository. If not, creating a new state machine and persist it.

The problem is that I have different types of state machines. The factory creates a StateMachine<UserState, UserEvent>, the repository returns a JpaRepositoryStateMachine. These are not compatible to each other and for me it is not clear how to persist / create / restore the state machines.

Can you please clarify that for me?

@Autowired
private StateMachineRepository<JpaRepositoryStateMachine> repository;

public someMethod(User user) {

Optional<JpaRepositoryStateMachine> stateMachine = repository.findById(user.getId()); // JPA state machine

if(stateMachine.isEmpty()) {
            StateMachine<UserState, UserEvent> createdStateMachine = factory.getStateMachine(user.getId()); // spring state machine
            repository.save(createdStateMachine); // compile error
        }

// here: ready-to-use statemachine - how?

}

Thanks for your help!

答案1

得分: 6

尝试使用SpringStateMachineService来获取状态机实例,而不是直接从存储库或工厂中显式检索。您可以使用Spring提供的默认实现

@Bean
public StateMachineService<State, Event> stateMachineService(
        final StateMachineFactory<State, Event> stateMachineFactory,
        final StateMachinePersist<WorkflowState, WorkflowEvent, String> stateMachinePersist) {
    return new DefaultStateMachineService<>(stateMachineFactory, stateMachinePersist);
}

这样,您的代码将如下所示:

@Autowired
private StateMachineService<State, Event> stateMachineService;

public void someMethod(User user) {
    StateMachine<State, Event> stateMachine = stateMachineService.acquireStateMachine(user.getId(), false);

    // 这里:可立即使用的状态机 - 例如调用stateMachine.start()

}

如果您进入acquireStateMachine方法,您会看到它通过ID从存储库查询状态机,并在未找到任何内容时创建一个新状态机。

您可以使用JpaPersistingStateMachineInterceptor来在每次更改时隐式保存和更新状态机实例。

@Bean
public JpaPersistingStateMachineInterceptor<State, Event, String>
        jpaPersistingStateMachineInterceptor() {
    return new JpaPersistingStateMachineInterceptor(stateMachineRepository);
}

详见持久化状态机

英文:

Try to use SpringStateMachineService to get a state machine instance instead of explicitly retrieving it from repository or factory. You can use default implementation provided by Spring:

@Bean
public StateMachineService&lt;State, Event&gt; stateMachineService(
        final StateMachineFactory&lt;State, Event&gt; stateMachineFactory,
        final StateMachinePersist&lt;WorkflowState, WorkflowEvent, String&gt; stateMachinePersist) {
    return new DefaultStateMachineService&lt;&gt;(stateMachineFactory, stateMachinePersist);
}

So, your code will look like:

@Autowired
private StateMachineService&lt;State, Event&gt; stateMachineService;

public someMethod(User user) {
StateMachine&lt;State, Event&gt; stateMachine = stateMachineService.acquireStateMachine(user.getId(), false);

// here: ready-to-use statemachine - call stateMachine.start() for example

}

If you go inside the acquireStateMachine method you can see that it queries state machine from repository by id and creates a new one if nothing found.

You can use JpaPersistingStateMachineInterceptor to implicitly save and update state machine instance on every change.

@Bean
public JpaPersistingStateMachineInterceptor&lt;State, Event, String&gt;
        jpaPersistingStateMachineInterceptor() {
    return new JpaPersistingStateMachineInterceptor(stateMachineRepository);
}

See Persisting State Machine

huangapple
  • 本文由 发表于 2020年9月21日 08:03:48
  • 转载请务必保留本文链接:https://go.coder-hub.com/63984734.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定