春季交易后的操作

时间:2014-09-11 06:20:15

标签: spring transactions locks

我在Spring有一种情况,我将数据写入某些外部源, 现在在将数据写入外部源之前,

  1. 我锁定
  2. 阅读对象
  3. 执行一些操作
  4. 写回来。并解锁对象。

  5. 下面的代码大致解释了我是如何做到的。

    //代码从这里开始

    Lock lck = new ReentrantLock();
    
    public void manipulateData(){
    
    lck.lock();
    //Object obj = read the data
    //modify it
    
    Write(obj)
    lck.unlock();
    
    }
    

    // Code End here

    现在在多线程环境中,当前发生的事情是在写入调用之后我正在调用unlock但是在我的函数执行完成之前我的事务没有提交。但是因为我打电话给解锁。其他线程获取锁并读取实际上正确的数据。

    所以我希望锁定应该只在事务提交时由其他线程获取。

    此外,我无法使用程序化交易。

2 个答案:

答案 0 :(得分:0)

您可以考虑提取读取对象的代码并将其修改为不同的方法(使用@Transactional注释)。然后应该在调用方法之前执行锁定,并在方法返回后释放。像这样:

@Autowired
private Dao dao;

public void manipulateData(){

    lck.lock();
    dao.update(myObj);
    lck.unlock();
}

class Dao {

    @Transactional
    public void update(MyObject obj) {
        //read and modify
    }
}

答案 1 :(得分:0)

您可以实现类似于此的Aspect(AOP):

首先创建一个类似于此的专有Transactional:

@Target({ ElementType.METHOD })
@Retention(RetentionPolicy.RUNTIME)
public @interface LockingTransactional {
}

然后,方面的有趣代码应与此类似:

    ...
    private final Lock lck = new ReentrantLock();
    ...

    @Around("@annotation(<FULL-PACKAGE-NAME-HERE>.LockingTransactional)")
    public Object intercept(ProceedingJoinPoint pjp) throws Throwable {
        try {
            lck.lock();
            TransactionStatus status = createTransaction(); // create the transaction "manually"
            Object result;
            try {
                result = pjp.proceed();
            } catch (Throwable t) { 
                txManager.rollback(status);
                throw t;
            }
            txManager.commit(status);
            return result;
        } finally {
            lck.unlock();
        }
    }

...

    private TransactionStatus createTransaction() {
        DefaultTransactionDefinition definition = new DefaultTransactionDefinition();
        def.setIsolationLevel(<YOUR-LEVEL-HERE>);
        def.setPropagationBehavior(<YOUR-PROPAGATION-HERE>);
        return txManager.getTransaction(definition);
    }

...