Java 为什么我能';无法在内存数据库中进行回滚?

Java 为什么我能';无法在内存数据库中进行回滚?,java,spring,hibernate,h2,Java,Spring,Hibernate,H2,我有一个测试类,它测试我的DAO类。从理论上讲,它应该先运行一个链→ 测验→ 之后在一个事务中进行回滚,但看起来不是这样。每次创建一个新id(123->456而不是123->123)。我猜内存中的DBs(我使用H2)就是这样工作的,我没有弄错。有了Postgres设置,它就足够好了 我查过: 配置、注释和传播级别 我试图使用hibernate.connection.autocommit=false HSQLDB 但我没有发现错误 TransactionSynchronizationManager

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

我查过:

  • 配置、注释和传播级别
  • 我试图使用
    hibernate.connection.autocommit=false
  • HSQLDB
  • 但我没有发现错误

    TransactionSynchronizationManager.isActualTransactionActive()
    返回
    true

    PersistenceConfig:

    @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;
        }
    }
    
    氢性质

    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

    @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());
        }
    }
    

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

    是什么让你认为交易没有被回滚

    分配了值为1、2、3的ID,尽管进行了回滚,H2数据库还是拒绝重用它们

    这里有一个关于这方面的讨论(在MySQL方面,但类似的行为)

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

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

    CustomerEntity veronicaCustomer = new CustomerEntity();
    veronicaCustomer.setid(1L);
    veronicaCustomer.setName("Veronica");
    
    根据这个问题(),它应该在H2中工作,没有任何问题。对于其他数据库(例如SQLServer),可能需要显式启用标识插入以手动设置标识列上的值