首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >java 4@事务嵌套事务问题

java 4@事务嵌套事务问题
EN

Stack Overflow用户
提问于 2016-04-20 08:42:20
回答 2查看 360关注 0票数 4

我有以下课程:

代码语言:javascript
复制
@Transactional
public class MyClass{
    @Transactional(propagation=Propagation.REQUIRES_NEW)
    public void method1(){
         ....
         myDao.update(entity);
    }

    public void method2(){
         method1();             
         //I need to be sure that data was persisted to DB and find the entity by id    

         MyEntity ent=myDao.find(entityId);
         //entity is not updated here
    }

}

但实际上,我无法从method2中的DB读取更新的实体。如何做到这一点?我需要在method2中在method1()调用之后更新值,因此应该提交method1中的事务,并且结果是可见的。怎么做?

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2016-04-20 08:50:41

您必须在另一个类中执行此操作,因为在调用本地方法时不遵守@Transactional (这取决于Spring代理的工作方式,本地方法调用this绕过事务代理)。

解决方案可能如下所示:

代码语言:javascript
复制
class Wrapper {
    public void performAction() {
       myClass.method1();
       myClass.find(entityId);
    }
}
票数 2
EN

Stack Overflow用户

发布于 2016-04-20 14:04:35

我重新创建了类似于(嵌入式数据库)的场景:首先,我向数据库添加了如下内容:

代码语言:javascript
复制
 public void initialize() {
    Sample startEntity = new Sample();
    startEntity.setId(1);
    startEntity.setName("Start name");
    sampleRepository.saveSample(startEntity);
    sampleRepository.flush(); // <-- just to make sure scenario is recreated
    sampleRepository.clear(); // same as above
    LOGGER.info(sampleRepository.findSampleById(1));
    sampleRepository.clear(); // same as above above :D
}

在此之后,我们在数据库中得到一个实体样本(所有事务都结束,缓存被清除);

控制台:

代码语言:javascript
复制
Hibernate: insert into sample (name, id) values (?, ?)
Hibernate: select sample0_.id as id1_0_0_, sample0_.name as name2_0_0_ from sample sample0_ where sample0_.id=?
2016-04-20 15:58:21.762  INFO 5764 --- [           main] com.patrykwoj.service.BasicServiceTest   : Sample [id=1, name=Start name]

现在你的例子是:

代码语言:javascript
复制
@Transactional
@Component
public class SampleService {

private static final Logger LOGGER = Logger.getLogger(SampleService.class);

@Autowired
SampleRepository sampleRepository;

@Transactional (propagation = Propagation.REQUIRES_NEW)
public void method1() {
    Sample someSample = new Sample();
    someSample.setId(1);
    someSample.setName("TestSample before update but after create");
    sampleRepository.updateSample(someSample);
}

public void method2() {
    method1();
    // I need to be sure that data was persisted to DB and find the entity by id

    Sample someSampleAfterUpdate = sampleRepository.findSampleById(1); //I believe that at that point sample is found in L-1 cache not in db directry.
    // entity is not updated here
    LOGGER.info(someSampleAfterUpdate); //in this point, transaction is not over yet, so you wont notice change in database..
}
}

然后从代码执行中获得控制台:

代码语言:javascript
复制
Hibernate: select sample0_.id as id1_0_0_, sample0_.name as name2_0_0_ from sample sample0_ where sample0_.id=?
2016-04-20 16:02:17.903  INFO 5044 --- [           main] com.patrykwoj.service.SampleService      : Sample [id=1, name=TestSample before update but after create]
Hibernate: update sample set name=? where id=?
2016-04-20 16:02:17.903  INFO 5044 --- [           main] com.patrykwoj.StackOverfloApplication    : Method2 is over

主修班:

代码语言:javascript
复制
@Override
public void run(String... strings) throws Exception {
  basicServiceTest.initialize();
  sampleService.method2();
  LOGGER.info("Method2 is over");
}

在我看来一切看起来都很好。它果然起作用了。我在您的代码中做了一些评论,但是控制台输出应该是清楚的。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/36738347

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档