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

Hibernate:如何在JUnit测试后回滚事务?,hibernate,transactions,junit,rollback,Hibernate,Transactions,Junit,Rollback,我在一个独立的应用程序中使用Hibernate 4.0.1.Final。底层数据库是MySQL 5.5。使用JUnit4.8.1,我正在测试我的数据访问对象,并希望运行测试,以便在JUnit测试结束时回滚所有更改。有没有一种优雅的方法可以做到这一点?现在,一切都在进行中,这是有道理的。这是我的JUnit测试 @Before public void setUp() throws IOException { final InputStream in = getClass().getClas

我在一个独立的应用程序中使用Hibernate 4.0.1.Final。底层数据库是MySQL 5.5。使用JUnit4.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;
}

这样做的方法是将提交和会话关闭与数据库操作分开。实际上,我认为这样做更好,因为不是每个数据库操作都应该是自己的事务。能够在多个操作中使用同一会话,并且能够在多个操作中使用同一事务,这有很大的优势

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

  • 这样做将使您能够更灵活地设计应用程序的业务规则,以处理不同数据库操作相互依赖的新情况,而无需在该数据库对象中编写一百万个方法来处理每个情况的不同事务规则
  • 不仅如此,将这些操作移出允许您在单元测试中实现所需的功能
  • 打开/关闭操作的成本很高,如果您在一行中执行5个查询,并且没有理由将它们放在单独的会话中,那么您不应该打开和关闭5个会话
    这样做的方法是将提交和会话关闭与数据库操作分开。实际上,我认为这样做更好,因为不是每个数据库操作都应该是自己的事务。能够在多个操作中使用同一会话,并且能够在多个操作中使用同一事务,这有很大的优势

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

  • 这样做将使您能够更灵活地设计应用程序的业务规则,以处理不同数据库操作相互依赖的新情况,而无需在该数据库对象中编写一百万个方法来处理每个情况的不同事务规则
  • 不仅如此,将这些操作移出允许您在单元测试中实现所需的功能
  • 打开/关闭操作的成本很高,如果您在一行中执行5个查询,并且没有理由将它们放在单独的会话中,那么您不应该打开和关闭5个会话
    我决定使用一个HSSql内存数据库,如下所述--。这样,我就可以反复运行JUnit测试(在服务级别),并保证每次运行时世界的状态都是相同的

    我决定使用内存中的HSSql数据库,如下所述--。这样,我就可以反复运行JUnit测试(在服务级别),并保证每次运行时世界的状态都是相同的

    我同意您关于将db操作与提交分离的观点。我在服务层看到了这一点。但是,我同样的问题也会出现——在测试服务层时,我将如何构造JUnit测试,以便在服务层操作之后,回滚数据库更改?这取决于您尝试测试的内容。也许您可以给您的数据库服务层一个模拟模式,如果它处于模拟模式,则不提交?我同意您关于将db操作与提交分离的观点。我在服务层看到了这一点。但是,我同样的问题也会出现——在测试服务层时,我将如何构造JUnit测试,以便在服务层操作之后,回滚数据库更改?这取决于您尝试测试的内容。也许您可以给您的数据库服务层一个模拟模式,如果它处于模拟模式,就不提交?