I'm trying to tweak the delete behaviour of the domain model of my application. Let's say I have Countries and Regions, and Countries should not be deleted if they have any Regions. The other classes / configuration will follow below, but the following code should test that. countryRepository.flush();
throws a DataIntegrityViolationException
, as expected, but the final call to countryRepository.count()
throws the same Exception. In the logs you can see it's trying to execute the DELETE SQL command again.
I was hoping on the @Transactional
to rollback the situation, but apparently it doesn't - perhaps because it's caught by 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() {
// Create objects
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();
// Deleting used countries should not be possible
Assertions.assertThrows(DataIntegrityViolationException.class, () -> {
countryRepository.delete(country);
countryRepository.flush();
});
Assert.assertEquals(1, countryRepository.count());
}
}
The data model:
@Entity
@Table(name = "countries")
public class Country {
@Id
public String name;
}
@Entity
@Table(name = "regions")
public class Region {
@Id
public String name;
@ManyToOne
public Country country;
}
the corresponding repositories:
public interface CountryRepository extends JpaRepository<Country, String> {
}
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
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>