gpt4 book ai didi

java - 并行事务如何产生OptimistickLockException?

转载 作者:行者123 更新时间:2023-12-01 13:09:54 29 4
gpt4 key购买 nike

我知道多种原因可以触发OptimistickLockException,但当前的测试用例要求两个事务同时写入相同的数据才能触发异常。更像是通过并行事务创建读/写违规问题。这就是我所做的:

  1. 在测试类中,创建一个私有(private)字段来保存事务和一些事务方法:

    private List<Transaction> transactions = new ArrayList<Transaction>();

    // This method only generate transactions and assign
    // them to the member field
    @Transactional
    public void retrieveTransactions(){
    transactions = generateTransactions(); // generateTransactions() is transactional
    }

    // Following two methods just write those
    // transactions into same summery, only the first one sleeps
    // during the process to make sure the second transaction
    // can occur in a parallel way
    @Transactional
    public void processTransactionsOne(){
    for(Transaction transaction:transactions){
    logger.info("====Transaction One=====");
    transaction.writeToSameSummary(); // writeToSameSummary() is transactional
    try {Thread.sleep(10000); } // sleep for 10 seconds before commit
    catch(InterruptedException ex) {}
    }
    }
    @Transactional
    public void processTransactionsTwo(){
    for(Transaction transaction:transactions){
    logger.info("====Transaction Two=====");
    transaction.writeToSameSummary(); // writeToSameSummary() is transactional
    }
    }
  2. applicationContext.xml中,我将上述三个方法设置为调度程序,retrieveTransactions每60秒运行一次,processTransactionsOneprocessTransactionsTwo 每 10 秒运行一次

    <task:scheduled ref="testBeanName" method="retrieveTransactions" cron="*/60 * * * * *"/>
    <task:scheduled ref="testBeanName" method="processTransactionsOne" cron="*/10 * * * * *"/>
    <task:scheduled ref="testBeanName" method="processTransactionsTwo" cron="*/10 * * * * *"/>

但是,我永远无法重现 OptimistickLockException 和显示的日志

====Transaction One=====
====Transaction One=====
====Transaction One=====
......
====Transaction Two=====
====Transaction Two=====
====Transaction Two=====

因此事务是同步运行的,而不是并行运行的。那么我如何(1)进行并行事务和(2)重现OptimistickLockException

最佳答案

要重现乐观锁定异常,请尝试从本身不是事务性的方法运行代码。例如,调用读取和修改实体的方法,并返回分离的副本。

然后调用相同的方法来修改相同的实体,并返回一个新的分离副本。与数据库相比,第一个副本现在已经过时了。尝试将第一个过时的副本合并到 session 中,它将抛出乐观锁定异常。

这是版本化实体的一些示例代码:

@Entity
public class MyEntity {
...
@Version
private Long version;
}

这是读取并返回分离实体的服务示例:

@Repository
public class SomeRepository {
@PersistenceContext
EntityManager em;

@Transactional
public MyEntity readAndModify(Long key) {
MyEntity myEntity = em.find( key, MyEntity.class);
myEntity.setSomeField(...); // this will trigger update via dirty checking
return myEntity;
}
}

测试中的这段代码可以触发乐观锁定异常:

public someNonTransactionalTest() {
//read and modify entity, get detached copy
MyEntity detachedCopy1 = someRepository.readAndModify(1L);

//read and modify entity, get another detached copy - copy 1 is stale now
MyEntity detachedCopy2 = someRepository.readAndModify(1L);

// try to merge the stale copy to a session, the optimistic locking exception is thrown
detachedCopy1 = entityManager.merge(detachedCopy1);

... assertions ...
}

关于java - 并行事务如何产生OptimistickLockException?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/22966928/

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