Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/388.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
java spring 4@事务嵌套事务问题_Java_Spring - Fatal编程技术网

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

java spring 4@事务嵌套事务问题,java,spring,Java,Spring,我有以下课程: @Transactional public class MyClass{ @Transactional(propagation=Propagation.REQUIRES_NEW) public void method1(){ .... myDao.update(entity); } public void method2(){ method1();

我有以下课程:

@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中的事务并显示结果。如何做到这一点?

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

解决方案可能如下所示:

class Wrapper {
    public void performAction() {
       myClass.method1();
       myClass.find(entityId);
    }
}

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

 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
}
现在请举一个例子:

@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..
}
}
然后从您的代码执行控制台:

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
主要类别:

@Override
public void run(String... strings) throws Exception {
  basicServiceTest.initialize();
  sampleService.method2();
  LOGGER.info("Method2 is over");
}

在我看来,一切看起来都很好。它像预期的那样工作。我对您的代码做了一些评论,但控制台输出应该是清晰的。

因为类级别的@Transactional method2和method1将在同一事务中运行。method1之后不会有提交,但您应该在method2中看到method1的保存/更新结果。如果你不这样做,那么问题就出在别处了。。。
@Override
public void run(String... strings) throws Exception {
  basicServiceTest.initialize();
  sampleService.method2();
  LOGGER.info("Method2 is over");
}