Note that there are some explanatory texts on larger screens.

plurals
  1. POInner transaction changes not visible to outer transaction
    primarykey
    data
    text
    <p>I'm using Spring3+JPA+Hibernate. I've tried to keep structure of the example similar to my actual code structure. Please scroll to the bottom for the actual question. Zipped maven project can be downloaded from www.esnips.com/nsdoc/da7a09c0-ce5a-4dbf-80a2-f414ea3bf333/?action=forceDL</p> <p>Following is the class under test.</p> <pre><code>public class ServiceImpl implements Service { @Autowired private DataAccessor dataAccessor; @Autowired private ServiceTransactions serviceTransactions; public Foo getFoo(long id) { return dataAccessor.getFoo(id); } public Foo createFoo(Foo foo) { return dataAccessor.createFoo(foo); } public Bar createBar(Bar bar) { return dataAccessor.createBar(bar); } @SuppressWarnings("unused") public Foo FooifyBar(long fooId, long barId) { Foo foo = dataAccessor.getFoo(fooId); Bar bar = dataAccessor.getBar(barId); return serviceTransactions.fooifyBar(fooId, barId, "Error"); } } </code></pre> <p>Following is the <code>ServiceTransactions</code> class.</p> <pre><code>public class ServiceTransactions { @Autowired private DataAccessor dataAccessor; @Transactional(propagation=Propagation.REQUIRES_NEW) public Foo fooifyBar(long fooId, long barId, String error) { Foo foo = dataAccessor.getFoo(fooId); Bar bar = dataAccessor.getBar(barId); return dataAccessor.fooifyBar(foo, bar, error); } } </code></pre> <p>Following is the implementation of <code>DataAccessor</code> in use.</p> <pre><code>public class DataAccessorImpl implements DataAccessor { @Autowired private DBController controller; @Transactional public Foo getFoo(long id) { FooDao food = controller.getFoo(id); return convertFoodToFoo(food); } @Transactional public Foo createFoo(Foo foo) { FooDao food = new FooDao(); food.setName(foo.getName()); return convertFoodToFoo(controller.createFoo(food)); } @Transactional public Bar getBar(long id) { return convertBardToBar(controller.getBar(id)); } @Transactional public Bar createBar(Bar bar) { BarDao bard = new BarDao(); bard.setName(bar.getName()); return convertBardToBar(controller.createBar(bard)); } @Transactional public Foo fooifyBar(Foo foo, Bar bar, String error) { return convertFoodToFoo(controller.fooBar(foo.getId(), bar.getId(), error)); } </code></pre> <p>Following is the implementation of <code>DBController</code></p> <pre><code>public class DBControllerImpl implements DBController { @PersistenceContext private EntityManager em; public FooDao getFoo(long id) { return em.find(FooDao.class, id); } public FooDao createFoo(FooDao foo) { em.persist(foo); return foo; } public BarDao getBar(long id) { return em.find(BarDao.class, id); } public BarDao createBar(BarDao bar) { em.persist(bar); return bar; } public FooDao fooBar(long fooId, long barId, String error) { FooDao foo = em.find(FooDao.class, fooId); FooedBarDao fb = new FooedBarDao(); fb.setFoo(foo); fb.setBar(em.find(BarDao.class, barId)); fb.setError(error); em.persist(fb); foo.getFooedBars().add(fb); em.merge(foo); return foo; } </code></pre> <p>And finally the test class</p> <pre><code>@RunWith(SpringJUnit4ClassRunner.class) @ContextConfiguration(locations="/testContext.xml") public class TestFooBar { @Autowired private Service service; Foo foo; Bar bar; @BeforeTransaction public void before() { foo = new Foo(); foo.setName("foo"); foo = service.createFoo(foo); bar = new Bar(); bar.setName("bar"); bar = service.createBar(bar); } @Test @Transactional public void testFooingBar() { service.FooifyBar(foo.getId(), bar.getId()); Foo foo2 = service.getFoo(foo.getId()); Assert.assertEquals(1, foo2.getFooedBars().size()); } </code></pre> <p><strong>Now the question is</strong> the test case fails with error <code>testFooingBar(com.test.sscce.server.TestFooBar): expected:&lt;1&gt; but was:&lt;0&gt;</code> in the form given above. If I modify the <code>FooifyBar</code> method in <code>ServiceImpl</code> class and remove the calls to <code>getFoo</code> and <code>getBar</code>, the test case succeeds without error. This means changes made by <code>fooifyBar</code> are not visible to the test method, if <code>getFoo</code> occurs before <code>fooifyBar</code>. Why is that?</p>
    singulars
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    plurals
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload