Skip to content

Commit 4801a4f

Browse files
mp911deschauder
authored andcommitted
#232 - Guard Repository.save(…) with provided Id with TransientDataAccessException if row does not exist.
We now emit a TransientDataAccessException if an object with a provided Id yields no affected rows. Such an arrangement is typically an indicator for a bug where calling code expects the object to be inserted with a provided Id.
1 parent 701e696 commit 4801a4f

File tree

2 files changed

+27
-3
lines changed

2 files changed

+27
-3
lines changed

src/main/java/org/springframework/data/r2dbc/repository/support/SimpleR2dbcRepository.java

+12-3
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,6 @@
1515
*/
1616
package org.springframework.data.r2dbc.repository.support;
1717

18-
import org.springframework.transaction.annotation.Transactional;
1918
import reactor.core.publisher.Flux;
2019
import reactor.core.publisher.Mono;
2120

@@ -24,6 +23,7 @@
2423

2524
import org.reactivestreams.Publisher;
2625

26+
import org.springframework.dao.TransientDataAccessResourceException;
2727
import org.springframework.data.r2dbc.convert.R2dbcConverter;
2828
import org.springframework.data.r2dbc.core.DatabaseClient;
2929
import org.springframework.data.r2dbc.core.PreparedOperation;
@@ -37,6 +37,7 @@
3737
import org.springframework.data.relational.core.sql.render.SqlRenderer;
3838
import org.springframework.data.relational.repository.query.RelationalEntityInformation;
3939
import org.springframework.data.repository.reactive.ReactiveCrudRepository;
40+
import org.springframework.transaction.annotation.Transactional;
4041
import org.springframework.util.Assert;
4142

4243
/**
@@ -83,8 +84,16 @@ public <S extends T> Mono<S> save(S objectToSave) {
8384
return this.databaseClient.update() //
8485
.table(this.entity.getJavaType()) //
8586
.table(this.entity.getTableName()).using(objectToSave) //
86-
.then() //
87-
.thenReturn(objectToSave);
87+
.fetch().rowsUpdated().handle((rowsUpdated, sink) -> {
88+
89+
if (rowsUpdated == 0) {
90+
sink.error(new TransientDataAccessResourceException(
91+
String.format("Failed to update table [%s]. Row with Id [%s] does not exist.",
92+
this.entity.getTableName(), this.entity.getId(objectToSave))));
93+
} else {
94+
sink.next(objectToSave);
95+
}
96+
});
8897
}
8998

9099
/* (non-Javadoc)

src/test/java/org/springframework/data/r2dbc/repository/support/H2SimpleR2dbcRepositoryIntegrationTests.java

+15
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@
2929

3030
import org.springframework.context.annotation.Configuration;
3131
import org.springframework.dao.DataAccessException;
32+
import org.springframework.dao.TransientDataAccessException;
3233
import org.springframework.data.r2dbc.config.AbstractR2dbcConfiguration;
3334
import org.springframework.data.r2dbc.testing.H2TestSupport;
3435
import org.springframework.test.context.ContextConfiguration;
@@ -82,4 +83,18 @@ public void shouldInsertNewObjectWithGivenId() {
8283
Map<String, Object> map = jdbc.queryForMap("SELECT * FROM legoset");
8384
assertThat(map).containsEntry("name", "SCHAUFELRADBAGGER").containsEntry("manual", 12).containsKey("id");
8485
}
86+
87+
@Test // gh-232
88+
public void updateShouldFailIfRowDoesNotExist() {
89+
90+
LegoSet legoSet = new LegoSet(9999, "SCHAUFELRADBAGGER", 12);
91+
92+
repository.save(legoSet) //
93+
.as(StepVerifier::create) //
94+
.verifyErrorSatisfies(actual -> {
95+
96+
assertThat(actual).isInstanceOf(TransientDataAccessException.class)
97+
.hasMessage("Failed to update table [legoset]. Row with Id [9999] does not exist.");
98+
});
99+
}
85100
}

0 commit comments

Comments
 (0)