Hibernate:如何在JUnit测试后回滚事务?

时间:2012-06-21 14:28:33

标签: hibernate transactions junit rollback

我在独立应用程序中使用Hibernate 4.0.1.Final。底层数据库是MySQL 5.5。使用JUnit 4.8.1,我正在测试我的数据访问对象,并希望运行测试,以便在我的JUnit测试结束时,我的所有更改都将被回滚。有一种优雅的方式吗?现在,一切都在承诺,这是有道理的。这是我的JUnit测试...

@Before
public void setUp() throws IOException { 
    final InputStream in = getClass().getClassLoader().getResourceAsStream("test.properties");
    testProps = new Properties();
    testProps.load(in);
    final Configuration configuration = new Configuration();
    configuration.configure().setProperty("hibernate.show_sql", "false");
    final ServiceRegistry serviceRegistry = new ServiceRegistryBuilder().applySettings(configuration.getProperties()).buildServiceRegistry();
    sessionFactory = configuration.buildSessionFactory(serviceRegistry);
    orgDao = new OrganizationDAOImpl(sessionFactory);
}   // setUp

@Test
public void testInsertSchool() { 
    final Organization org = new Organization();
    org.setOrganizationId(testProps.getProperty("test.id"));
    org.setName(testProps.getProperty("test.name"));
    orgDao.saveOrUpdate(org);
    final Organization foundOrg = orgDao.findById(org.getOrganizationId());
    Assert.assertEquals(org, foundOrg);
}

以下是数据访问对象的代码......

protected void saveOrUpdate(Object obj) {
    try {
        startOperation();
        session.saveOrUpdate(obj);
        tx.commit();
    } catch (HibernateException e) {
        handleException(e);
    } finally {
        session.close();
    }
}

protected Object find(Class clazz, Serializable id) {
    Object obj = null;
    try {
        startOperation();
        obj = session.get(clazz, id);
        tx.commit();
    } catch (HibernateException e) {
        handleException(e);
    } finally {
        session.close();
    }
    return obj;
}

2 个答案:

答案 0 :(得分:1)

我决定使用HSSql内存数据库,如此处所述 - http://vageeshhoskere.wordpress.com/2011/06/16/unit-test-with-junit-for-hibernate-using-hsqldb-in-memory/。这样,我可以重复运行JUnit测试(在服务级别)并保证每次运行时世界状态都是相同的。

答案 1 :(得分:0)

这样做的方法是从数据库操作中分离出提交和会话关闭。实际上我认为最好这样做,因为不是每个数据库操作都应该是它自己的事务。能够在多个操作中使用相同的会话并将相同的事务用于多个操作具有显着的优点。

我描述事务层的方式是业务规则问题,因为它们定义了数据库级别的原子工作单元。它应该是从图层中抽出hibernate操作进行持久化,查找和合并的一层。这是为什么:

  1. 这样做可以更灵活地设计应用程序的业务规则,以处理不同数据库操作相互依赖的新案例,而不必强迫您在该数据库对象中编写一百万个方法来处理不同的事务规则每个案例。
  2. 不仅如此,将这些操作移出也可以让您在单元测试中实现所需。
  3. 打开/关闭操作非常昂贵,如果您连续进行5次查询并且没有理由将它们放在单独的会话中,则不应该打开和关闭5个会话。