1

我正在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),我看不到更改,所以我的断言总是失败。

我的配置有什么问题?

4

2 回答 2

3

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

于 2012-08-28T11:01:37.990 回答
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 刷新的结果,您可以在同一个事务中执行它,例如,使用sessionFactory.getCurrentSession().doWork(...).

于 2012-08-28T11:41:03.137 回答