gpt4 book ai didi

persistence - 在 Spring Statemachine 中持久化和恢复当前状态

转载 作者:行者123 更新时间:2023-12-04 21:12:56 32 4
gpt4 key购买 nike

我将 Spring Statemachine 引入到现有项目中,希望能够合并和澄清我们的业务逻辑。我们有各种具有互连状态的 JPA 实体,我在将持久状态设置为现有状态机的当前状态时遇到了一些麻烦。

我正在使用 StateMachineFactory 为每个实体实例创建一个新的 StateMachine 实例。我将 StateMachine 的当前状态存储在一个单独的字段中以供 Hibernate 持久保存,并且理想情况下需要将持久字段的值与 StateMachine 同步。我的问题是如何在 Spring Statemachine 中实现这一点。

@Entity
@EntityListeners(MyEntityListener.class)
public class MyEntity {

@Column
private MyState internalState; // Using AttributeConverter

@Transient
private StateMachine<MyState, Event> stateMachine;

}

public class MyEntityListener {

@PostLoad
public void postLoad(MyEntity entity) {
// TODO Set StateMachine's current state to entity's internal state
);

}
  • 一种方法可能是定义局部转换以将初始状态移动到持久状态。然后我可以进行条件检查以找到与本地转换相关的事件,这会将源状态移动到目标状态。这对我来说似乎有点乱,我想保持状态机的配置尽可能干净。
  • 我看不到如何通过公共(public) API 设置 StateMachine 的当前状态而不通过转换,因此我探索的另一种方法是包装 StateMachine 实例以公开以下方法(因为它是方便的默认范围):

  • package org.springframework.statemachine.support;

    public abstract class AbstractStateMachine<S, E> extends StateMachineObjectSupport<S, E> implements StateMachine<S, E>, StateMachineAccess<S, E> {

    void setCurrentState(State<S, E> state, Message<E> message, Transition<S, E> transition, boolean exit, StateMachine<S, E> stateMachine)

    }

    package org.springframework.statemachine.support;

    public class MyStateMachineWrapper<S, E> {

    private AbstractStateMachine<S, E> stateMachine;

    public MyStateMachineWrapper(StateMachine<S, E> stateMachine) {
    if (stateMachine instanceof AbstractStateMachine) {
    this.stateMachine = (AbstractStateMachine<S, E>)stateMachine;
    } else {
    throw new IllegalArgumentException("Provided StateMachine is not a valid type");
    }
    }

    public void setCurrentState(S status) {
    stateMachine.setCurrentState(findState(status), null, null, false, stateMachine);
    }

    private State<S, E> findState(S status) {
    for (State<S, E> state : stateMachine.getStates()) {
    if (state.getId() == status) {
    return state;
    }
    }

    throw new IllegalArgumentException("Specified status does not equate to valid State");
    }
    }

    然后我可以将以下代码放入 MyEntityListener.postLoad:

    MyStateMachineWrapper<MyState, Event> myStateMachineWrapper = new MyStateMachineWrapper<>(entity.getStateMachine());
    myStateMachineWrapper.setCurrentState(entity.getInternalState());

    上述方法似乎工作正常,但我无法想象这是设想的工作方式。肯定有一种更简洁的方法可以实现这一点,或者该项目还不够成熟并且还不包含此功能?

    感谢您的任何想法和意见。

    最佳答案

    我已经清理了上面的选项 #2,将包装类更改为 utils 类。需要明确的是,这种方法利用了具有默认访问器的 setCurrentState 方法,因此这可能最终成为一个脆弱的解决方案。

    package org.springframework.statemachine.support;

    public abstract class MyStateMachineUtils extends StateMachineUtils {

    public static <S, E> void setCurrentState(StateMachine<S, E> stateMachine, S state) {
    if (stateMachine instanceof AbstractStateMachine) {
    setCurrentState((AbstractStateMachine<S, E>)stateMachine, state);
    } else {
    throw new IllegalArgumentException("Provided StateMachine is not a valid type");
    }
    }

    public static <S, E> void setCurrentState(AbstractStateMachine<S, E> stateMachine, S state) {
    stateMachine.setCurrentState(findState(stateMachine, state), null, null, false, stateMachine);
    }

    private static <S, E> State<S, E> findState(AbstractStateMachine<S, E> stateMachine, S stateId) {
    for (State<S, E> state : stateMachine.getStates()) {
    if (state.getId() == stateId) {
    return state;
    }
    }

    throw new IllegalArgumentException("Specified State ID is not valid");
    }
    }

    然后可以像这样很好地使用它:

    MyStateMachineUtils.setCurrentState(entity.getStateMachine(), entity.getInternalState());

    关于persistence - 在 Spring Statemachine 中持久化和恢复当前状态,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/30595534/

    32 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com