首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >为什么我不能对内存中的DB进行回滚?

问为什么我不能对内存中的DB进行回滚?
EN

Stack Overflow用户
提问于 2019-07-16 12:43:20
回答 1查看 975关注 0票数 0

我有测试类,测试我的DAO类。理论上,它应该在一个事务中运行→测试→之前的每个链,然后再进行回滚,但看起来并非如此。每次创建一个新id (123->456而不是123->123)。我猜内存中的DB(我使用H2)就是这样工作的,我没有弄错。随着Postgres的设置,它的工作足够好。

我查过了:

  1. 配置、注释和传播级别
  2. 我试着用hibernate.connection.autocommit = false
  3. HSQLDB

但我在那没有发现任何错误。

TransactionSynchronizationManager.isActualTransactionActive()返回true。

PersistenceConfig:

代码语言:javascript
复制
@Configuration
@ComponentScan("com.beginnercourse.softcomputer")
@PropertySource({"classpath:persistence-postgres.properties"})
@PropertySource({"classpath:persistence-h2.properties"})
@EnableTransactionManagement
public class PersistenceConfig {

    @Autowired
    private Environment environment;

    @Bean
    @Autowired
    public HibernateTransactionManager transactionManager(SessionFactory sessionFactory) {
        HibernateTransactionManager transactionManager = new HibernateTransactionManager();
        transactionManager.setSessionFactory(sessionFactory);
        return transactionManager;
    }

    @Bean
    @Profile("postgres")
    public DataSource postgresDataSource() {
        BasicDataSource dataSource = new BasicDataSource();
        dataSource.setDriverClassName(requireNonNull(environment.getProperty("jdbc.postgres.driverClassName")));
        dataSource.setUrl(requireNonNull(environment.getProperty("jdbc.postgres.connection_url")));
        dataSource.setUsername(requireNonNull(environment.getProperty("jdbc.postgres.username")));
        dataSource.setPassword(requireNonNull(environment.getProperty("jdbc.postgres.password")));

        return dataSource;
    }

    @Bean
    @Profile("postgres")
    public LocalSessionFactoryBean postgresSessionFactory() {
        LocalSessionFactoryBean sessionFactory = new LocalSessionFactoryBean();
        sessionFactory.setDataSource(postgresDataSource());
        sessionFactory.setPackagesToScan(
                new String[]{"com.beginnercourse.softcomputer"});
        sessionFactory.setHibernateProperties(postgresAdditionalProperties());

        return sessionFactory;
    }

    private Properties postgresAdditionalProperties() {
        final Properties hibernateProperties = new Properties();

        hibernateProperties.setProperty("hibernate.hbm2ddl.auto", requireNonNull(environment.getProperty("hibernate.postgres.hbm2ddl.auto")));
        hibernateProperties.setProperty("hibernate.dialect", requireNonNull(environment.getProperty("hibernate.postgres.dialect")));
        hibernateProperties.setProperty("hibernate.show_sql", requireNonNull(environment.getProperty("hibernate.postgres.show_sql")));
        hibernateProperties.setProperty("hibernate.default_schema", requireNonNull(environment.getProperty("hibernate.postgres.default_schema")));
//        hibernateProperties.setProperty("hibernate.cache.use_second_level_cache", requireNonNull(environment.getProperty("hibernate.cache.use_second_level_cache")));
//        hibernateProperties.setProperty("hibernate.cache.use_query_cache", requireNonNull(environment.getProperty("hibernate.cache.use_query_cache")));

        return hibernateProperties;
    }

    @Bean
    @Profile("oracle")
    public DataSource oracleDataSource() throws NamingException {
        return (DataSource) new JndiTemplate().lookup(requireNonNull(environment.getProperty("jdbc.url")));
    }


    @Bean
    @Profile("test")
    public LocalSessionFactoryBean testSessionFactory(DataSource dataSource ) {
        LocalSessionFactoryBean sessionFactory = new LocalSessionFactoryBean();
//        postgresSessionFactory.setDataSource(postgresDataSource());
        sessionFactory.setDataSource(dataSource);
        sessionFactory.setPackagesToScan(
                new String[]{"com.beginnercourse.softcomputer"});
        sessionFactory.setHibernateProperties(testAdditionalProperties());

        return sessionFactory;
    }

    @Bean
    @Profile("test")
    public DataSource h2DataSource() {
        BasicDataSource dataSource = new BasicDataSource();
        dataSource.setDriverClassName(requireNonNull(environment.getProperty("jdbc.h2.driverClassName")));
        dataSource.setUrl(requireNonNull(environment.getProperty("jdbc.h2.connection_url")));
        dataSource.setUsername(requireNonNull(environment.getProperty("jdbc.h2.username")));
        dataSource.setPassword(requireNonNull(environment.getProperty("jdbc.h2.password")));
        return dataSource;
    }

    private Properties testAdditionalProperties() {
        final Properties hibernateProperties = new Properties();

        hibernateProperties.setProperty("hibernate.hbm2ddl.auto", requireNonNull(environment.getProperty("hibernate.h2.hbm2ddl.auto")));
        hibernateProperties.setProperty("hibernate.dialect", requireNonNull(environment.getProperty("hibernate.h2.dialect")));
        hibernateProperties.setProperty("hibernate.show_sql", requireNonNull(environment.getProperty("hibernate.h2.show_sql")));
        hibernateProperties.setProperty("hibernate.globally_quoted_identifiers", requireNonNull(environment.getProperty("hibernate.h2.globally_quoted_identifiers")));
        hibernateProperties.setProperty("hibernate.connection.autocommit", requireNonNull(environment.getProperty("hibernate.h2.connection.autocommit")));

        return hibernateProperties;
    }
}

H2属性

代码语言:javascript
复制
jdbc.h2.driverClassName=org.h2.Driver
jdbc.h2.connection_url=jdbc:h2:mem:e-commerce
jdbc.h2.username=sa
jdbc.h2.password=sa

hibernate.h2.dialect=org.hibernate.dialect.H2Dialect
hibernate.h2.show_sql=false
hibernate.h2.hbm2ddl.auto=update
hibernate.h2.globally_quoted_identifiers=true
hibernate.h2.connection.autocommit = false

TestDaoImpl

代码语言:javascript
复制
@ActiveProfiles(profiles = "test")
//@ActiveProfiles(profiles = "postgres")
@RunWith(SpringRunner.class)
@ContextConfiguration(classes = {
        WebConfig.class,
        PersistenceConfig.class,
})
@WebAppConfiguration
@Transactional
@Rollback
public class CustomerDaoImplTest {

    @Autowired
    private CustomerDao customerDao;

    @Before
    public void setUp() throws Exception {
        CustomerEntity veronicaCustomer = new CustomerEntity();
        veronicaCustomer.setName("Veronica");
        customerDao.create(veronicaCustomer);
        CustomerEntity hannaCustomer = new CustomerEntity();
        hannaCustomer.setName("Hanna");
        customerDao.create(hannaCustomer);
        CustomerEntity ericCustomer = new CustomerEntity();
        ericCustomer.setName("Eric");
        customerDao.create(ericCustomer);
    }

    @After
    public void tearDown() throws Exception {
        customerDao.remove((long) 1);
        customerDao.remove((long) 2);
        customerDao.remove((long) 3);
    }

    @Test
    public void find_must_return_an_object_by_id() throws NoCustomerWithSuchParametersException {
        CustomerEntity customer = new CustomerEntity();
        customer.setName("Veronica");
        assertEquals(customerDao.find((long) 1).get().getName(), customer.getName());


    }

    @Test(expected = EntityNotFoundException.class)
    public void should_optional_empty() {
        assertEquals(customerDao.find((long) 55), Optional.empty());
    }
}

还有其他人遇到过类似的事情吗?

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2019-07-16 14:32:55

是什么使您认为事务没有被回滚?

值为1、2、3的Ids被分配,尽管回滚,H2数据库还是拒绝重用它们。

这里有一个关于这一点的讨论(关于MySQL,但类似的行为) INCREMENT does not ROLLBACK。

您可以在测试之间重置自动增量值:

Resetting autoincrement in h2

或者您可以简单地更新代码以手动设置标识符:

代码语言:javascript
复制
CustomerEntity veronicaCustomer = new CustomerEntity();
veronicaCustomer.setid(1L);
veronicaCustomer.setName("Veronica");

根据这个问题(INSERT ),它应该在H2中工作,没有任何问题。对于其他数据库(例如,SQLServer),您可能需要显式地启用标识插入来手动设置标识列的值。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/57057556

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档