刷新后无法看到Hibernate会话之外的更改

时间:2012-08-28 10:58:56

标签: java spring hibernate flush

我正在Spring 3.1.2使用Hibernate 4

我有一个用MyDaoImpl注释的DAO实现类@Repository,以便启用异常转换。我的服务类MyService注明了@Transactional,如下所示:

public class MyDaoImpl implements MyDao {

    private SessionFactory sessionFactory;

    @Autowired
    public void setSessionFactory(SessionFactory sessionFactory) {
       this.sessionFactory = sessionFactory;
    }

    @Override
    public void saveA(A a)
    {
        this.sessionFactory.getCurrentSession().saveOrUpdate(a);
    }
}

我写了一个单元测试类MyDaoImplTest,如下所示:

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations = { "classpath:beans.xml" })
@Transactional
public class MyDaoImplTest implements IMyDaoImplTest {

    private MyDao myDao;

    private SessionFactory sessionFactory;

    @Autowired
    public void setMyDao(MyDao myDao)
    {
        this.myDao = myDao;
    }

    @Autowired
    public void setSessionFactory(SessionFactory sessionFactory)
    {
        this.sessionFactory = sessionFactory;
    }

    @Test
    @Override
    public void testCreateA()
    {
       A a = new A("A1");
       this.myDao.saveA(a);

       this.sessionFactory.getCurrentSession().flush();

       IDataSet databaseDataSet = this.getConnection().createDataSet();
       ITable actualTable = databaseDataSet.getTable("Applications");

   IDataSet expectedDataSet = new FlatXmlDataSetBuilder().build(this.getClass().getClassLoader().getResourceAsStream("test-data/applications/savenew.xml"));
   ITable expectedTable = expectedDataSet.getTable("Applications");

   Assertion.assertEquals(expectedTable, actualTable);
    }
}

根据Spring文档,我在更改后刷新会话以避免误报。问题是,在刷新之后,如果我在Hibernate之外访问数据库(例如使用DBUnit),我看不到更改,所以我的断言总是失败。

我的配置有什么问题?

2 个答案:

答案 0 :(得分:3)

这是预期的行为。 Flush是与事务提交不同的概念。只有在提交后才能看到事务之外的更改。

答案 1 :(得分:0)

如果要在事务提交后检查数据库的状态,则有两个选项:

  • 检查用@AfterTransaction注释的方法。在@Tranactional测试方法定义的事务结束后,Spring JUnit运行程序将执行此方法。不要忘记禁用自动事务回滚(@TransactionConfiguration(defaultRollback = false))。如果您需要对不同的测试方法进行不同的检查,您可以执行以下操作:

    private Runnable check;
    
    @AfterTransaction
    public void performCheck() {
        if (check != null) check.run();
    }
    
    @Test
    @Override
    public void testCreateA() {
        ... // Code being tested
        check = new Runnable() {
            public void run() {
                ... // Code to check the state
            }
        };
    }
    
  • 在测试方法中使用程序化事务划分:

    private TransactionTemplate tx;
    
    @Autowired
    private void setTransactionManager(PlatformTransactionManager ptm) {
        tx = new TransactionTemplate(ptm);
    }
    
    @Test
    @Override
    @Transactional(progrgation = Propagation.NOT_SUPPORTED) // Disable declarative transaction
    public void testCreateA() {
        tx.execute(...); // Code to test
        tx.execute(...); // Check
    }
    

或者,如果您的目标是使用DbUnit检查Hibernate flush的结果,则可以在同一事务中执行此操作,例如,使用sessionFactory.getCurrentSession().doWork(...)