首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >使用MySQL 8的事务性Spring引导测试回滚事务,但无论如何都会插入行

使用MySQL 8的事务性Spring引导测试回滚事务,但无论如何都会插入行
EN

Stack Overflow用户
提问于 2019-10-04 02:37:56
回答 3查看 821关注 0票数 1

通常,当我使用Spring Data JPA做Spring Boot应用程序时,在测试中事务会自动回滚,测试数据库不会改变。然而,这种行为在MySQL8中不起作用。

我有一个名为Category的小POJO。

代码语言:javascript
复制
@Entity
@Table(name = "categories")
public class Category {
    @Id @GeneratedValue(strategy = GenerationType.IDENTITY)
    @Column(name = "category_id")
    private Integer id;

    @Column(name = "category_name")
    private String name;

    // ... constructors, getters and setters, etc, omitted ...
}

下面是我的更简单的存储库接口:

代码语言:javascript
复制
public interface CategoryRepository extends JpaRepository<Category,Integer> {
}

我有一个现有的数据库,下面是访问它的application.properties设置:

代码语言:javascript
复制
spring.datasource.url=jdbc:mysql://localhost:3306/dashboard
spring.datasource.username=admin
spring.datasource.password=not_password
spring.jpa.show-sql=true
spring.jpa.hibernate.ddl-auto=update
spring.jpa.properties.hibernate.format_sql=true
spring.jpa.properties.hibernate.dialect=org.hibernate.dialect.MySQL8Dialect

表中目前有10个类别。我的测试检查它们,另一个测试插入一个新的。

代码语言:javascript
复制
@DataJpaTest
@AutoConfigureTestDatabase(replace= AutoConfigureTestDatabase.Replace.NONE)
class CategoryRepositoryTest {
    @Autowired
    private CategoryRepository dao;

    @Test
    void findAll() {
        List<Category> categories = dao.findAll();
        assertEquals(10, categories.size());
    }

    @Test
    void insertCategory() {
        Category cat = new Category("Misc");
        assertNull(cat.getId());
        cat = dao.save(cat);
        assertNotNull(cat.getId());
        System.out.println(cat);
    }
}

请注意,@DataJpaTest已经包含了@Transactional。第二个测试的输出为:

代码语言:javascript
复制
2019-10-03 14:26:48.844  INFO 91485 --- [    Test worker] o.s.t.c.transaction.TransactionContext   : Began transaction (1) for test context [DefaultTestContext@67e4b73d testClass = CategoryRepositoryTest, testInstance = com.kousenit.simpledemo.dao.CategoryRepositoryTest@3913544f, testMethod = insertCategory@CategoryRepositoryTest, testException = [null], mergedContextConfiguration = [MergedContextConfiguration@7314dd45 testClass = CategoryRepositoryTest, locations = '{}', classes = '{class com.kousenit.simpledemo.MyApplication}', contextInitializerClasses = '[]', activeProfiles = '{}', propertySourceLocations = '{}', propertySourceProperties = '{org.springframework.boot.test.autoconfigure.orm.jpa.DataJpaTestContextBootstrapper=true}', contextCustomizers = set[org.springframework.boot.test.autoconfigure.OverrideAutoConfigurationContextCustomizerFactory$DisableAutoConfigurationContextCustomizer@3c6df497, org.springframework.boot.test.autoconfigure.filter.TypeExcludeFiltersContextCustomizer@351584c0, org.springframework.boot.test.autoconfigure.properties.PropertyMappingContextCustomizer@8b9f8fd, org.springframework.boot.test.autoconfigure.web.servlet.WebDriverContextCustomizerFactory$Customizer@15acb0c6, [ImportsContextCustomizer@76c5962 key = [org.springframework.boot.autoconfigure.cache.CacheAutoConfiguration, org.springframework.boot.autoconfigure.data.jpa.JpaRepositoriesAutoConfiguration, org.springframework.boot.autoconfigure.flyway.FlywayAutoConfiguration, org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration, org.springframework.boot.autoconfigure.jdbc.DataSourceTransactionManagerAutoConfiguration, org.springframework.boot.autoconfigure.jdbc.JdbcTemplateAutoConfiguration, org.springframework.boot.autoconfigure.liquibase.LiquibaseAutoConfiguration, org.springframework.boot.autoconfigure.orm.jpa.HibernateJpaAutoConfiguration, org.springframework.boot.autoconfigure.transaction.TransactionAutoConfiguration, org.springframework.boot.test.autoconfigure.jdbc.TestDatabaseAutoConfiguration, org.springframework.boot.test.autoconfigure.orm.jpa.TestEntityManagerAutoConfiguration]], org.springframework.boot.test.context.filter.ExcludeFilterContextCustomizer@21f27cf2, org.springframework.boot.test.json.DuplicateJsonObjectContextCustomizerFactory$DuplicateJsonObjectContextCustomizer@67568498, org.springframework.boot.test.mock.mockito.MockitoContextCustomizer@0], contextLoader = 'org.springframework.boot.test.context.SpringBootContextLoader', parent = [null]], attributes = map[[empty]]]; transaction manager [org.springframework.orm.jpa.JpaTransactionManager@4a3861f3]; rollback [true]
Hibernate: 
    insert 
    into
        categories
        (category_name) 
    values
        (?)
Category{id=11, name='Misc'}
2019-10-03 14:26:48.880  INFO 91485 --- [    Test worker] o.s.t.c.transaction.TransactionContext   : Rolled back transaction for test: [DefaultTestContext@67e4b73d testClass = CategoryRepositoryTest, testInstance = com.kousenit.simpledemo.dao.CategoryRepositoryTest@3913544f, testMethod = insertCategory@CategoryRepositoryTest, ...

问题是,测试结束后,我的数据库中仍然有新的类别。在H2中,事务回滚了,但是在MySQL 8中,即使发生了回滚,插入的项仍然存在。

这里有什么不同?我如何修复它,以便在测试结束时重置插入?

EN

回答 3

Stack Overflow用户

发布于 2019-10-04 02:52:26

因为事务需要显式提交。因此,我认为您需要将自动提交的属性设置为false。像这样

代码语言:javascript
复制
<property name="hibernate.connection.autocommit">false</property>
票数 0
EN

Stack Overflow用户

发布于 2019-10-04 16:18:39

将您的测试方法设置为公共的,因为从documentation

由于Spring框架基于代理的本质,根据定义,目标对象内的调用不会被拦截。对于JDK代理,只能拦截代理上的公共接口方法调用。

如果该方法不是公共的,则不会引发任何错误。

我想您使用的是缺省设置(JDK代理,而不是CGLIB)

票数 0
EN

Stack Overflow用户

发布于 2021-03-31 19:20:53

我不确定这是不是你的问题,但我得到了相同的行为,因为我在一个创建线程和它自己的事务的流中使用了"peek“,当所有测试一起运行时,它在数据库中留下了行。当它们一个接一个地运行时,这并没有发生。确保没有创建新的线程,也没有在代码内部进行控制

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

https://stackoverflow.com/questions/58225093

复制
相关文章

相似问题

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