在StaleObjectStateException

时间:2019-01-10 16:16:00

标签: java hibernate staleobjectstateexception

StaleObjectStateExceptions可能是在具有多个服务器/线程的应用程序上使用Hibernate的不可避免的部分,并且通常的做法是让失败者以安全的方式短暂延迟后重试。 为了最佳实践的利益,我想创建一个强制执行安全性的框架,这样,如果重试会导致数据丢失,它将被中止并抛出异常,以迫使开发人员调查对象为何具有主题的字段。适应比赛条件并进行相应修复。

不幸的是,到目前为止,我生产的产品感觉欠佳,并且包含了我认为很多样板代码,这意味着其他开发人员不太可能在需要时使用它。 下面的ExampleRetryableUpdate如何进行改进,特别是对于具有多个字段要同时更新的Update Runnable?

public class ExampleRetryableUpdate extends SafeRetryableUpdateRunnable<Model>{
    private Long id;
    private String originalState;
    private String targetState;

    public ExampleRetryableUpdate(Model targetState, Model currentState){
        this.originalState = currentState.getFieldToUpdate();
        this.targetState = targetState.getFieldToUpdate();
    }

    @Override
    boolean safeToUpdate(Model current) {
        return originalState.equals(current.getFieldToUpdate());
    }

    @Override
    String getStaleFields(Model current) {
        StringBuilder sb = new StringBuilder();
        if(!this.originalState.equals(current.getFieldToUpdate())){
            sb.append("FieldToUpdate differs: Stale - ");
            sb.append(this.originalState);
            sb.append(", Current - ");
            sb.append(current.getFieldToUpdate());
        }
        //Repeatable for each relevant field
        return sb.toString();
    }

    @Override
    public void run() {
        try{
            Model current = Model.findById(id);
            if(safeToUpdate(current)){
                current.setFieldToUpdate(targetState);
                Model.persist(current);
            } else{
                throw new UnsafeRetryException(getStaleFields(current));
            }
        } catch (StaleObjectStateException ex){
            System.out.println("Failed due to StaleObject exception, may retry.");
            throw ex;
        }

    }
}

上下文类:

public abstract class SafeRetryableUpdateRunnable<T> implements Runnable {
    abstract boolean safeToUpdate(T Model);
    abstract String getStaleFields(T current);
}

public class Model {
    private Long id;
    private String fieldToUpdate;
    private String irrelevantField;
    private Integer oca;

    public String getFieldToUpdate() {
        return fieldToUpdate;
    }

    public void setFieldToUpdate(String fieldToUpdate) {
        this.fieldToUpdate = fieldToUpdate;
    }
...
}

public class BusinessLogicClass {
    public boolean someMethod() throws InterruptedException {
        //Business logic
        //...
        //Get current from Db, create a copy and alter fieldToUpdate
        //...
        ExampleRetryableUpdate runnable = new ExampleRetryableUpdate(targetState, currentState);
        int i = 0;
        do{
            try{
                runnable.run();
                return true;
            } catch(StaleObjectStateException ex){
                System.out.println("Expected, potentially retryable.");
                Thread.sleep(1000L);
            } catch(UnsafeRetryException ex){
                System.out.println("Field has been updated by an alternate thread/server. Aborting.");
                return false;
            }
        }while (i++ <= 3);
        return false;
    }
}

0 个答案:

没有答案
相关问题