You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

JpaRepository刷新后删除对象失败,如何执行回滚操作?

关联实体删除限制测试中的事务异常问题

我正在调整应用领域模型的删除逻辑:当Country关联有Region时,禁止删除该Country。测试过程中,countryRepository.flush();按预期抛出DataIntegrityViolationException,但后续调用countryRepository.count()时又再次抛出相同异常,日志显示DELETE SQL命令被重复执行。我原本以为@Transactional会自动回滚操作,但实际并未生效,推测是assertThrows捕获异常导致事务未触发回滚。

测试代码

@SpringBootTest
@SpringBootApplication
@TestPropertySource(locations = "classpath:unit-tests.properties")
@Transactional
public class Tests {
    @Autowired
    private CountryRepository countryRepository;

    @Autowired
    private RegionRepository regionRepository;

    @Test
    public void preventDeleteOfUsedObjects() {
        // 创建测试对象
        Country country = new Country();
        country.name = "United Status";
        countryRepository.save(country);
        countryRepository.flush();
        Region region = new Region();
        region.name = "California";
        region.country = country;
        regionRepository.save(region);
        regionRepository.flush();

        // 尝试删除关联有Region的Country,预期失败
        Assertions.assertThrows(DataIntegrityViolationException.class, () -> {
            countryRepository.delete(country);
            countryRepository.flush();
        });

        Assert.assertEquals(1, countryRepository.count());
    }
}

数据模型

Country实体

@Entity
@Table(name = "countries")
public class Country {
    @Id
    public String name;
}

Region实体

@Entity
@Table(name = "regions")
public class Region {
    @Id
    public String name;

    @ManyToOne
    public Country country;
}

数据仓库

CountryRepository

public interface CountryRepository extends JpaRepository<Country, String> {
}

RegionRepository

public interface RegionRepository extends JpaRepository<Region, String> {
}

测试配置文件(unit-tests.properties)

spring.datasource.url=jdbc:hsqldb:mem:model;sql.syntax_pgs=true
spring.datasource.username=sa
spring.datasource.password=
spring.datasource.driver-class-name=org.hsqldb.jdbcDriver
spring.jackson.default-property-inclusion=non_null
spring.jpa.hibernate.ddl-auto=create
spring.jpa.hibernate.naming.physical-strategy=org.hibernate.boot.model.naming.PhysicalNamingStrategyStandardImpl
logging.level.org.hibernate.SQL=DEBUG
logging.level.org.hibernate.type.descriptor.sql.BasicBinder=TRACE
logging.level.root=INFO

Maven配置(pom.xml)

<project xmlns="http://maven.apache.org/POM/4.0.0"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.6.6</version>
        <relativePath/>
    </parent>
    <artifactId>example</artifactId>
    <name>example</name>
    <properties>
        <maven.compiler.release>11</maven.compiler.release>
    </properties>
    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-data-jpa</artifactId>
        </dependency>
        <dependency>
            <groupId>org.hibernate</groupId>
            <artifactId>hibernate-core</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>org.hsqldb</groupId>
            <artifactId>hsqldb</artifactId>
            <scope>test</scope>
        </dependency>
    </dependencies>
</project>

内容的提问来源于stack exchange,提问作者Glorfindel

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.13 11:48:20