Spring Data R2DBC

TODO

  1. https://www.vinsguru.com/spring-data-r2dbc/
  2. https://www.vinsguru.com/spring-data-r2dbc-transaction/

TransientDataAccessResourceException

While doing insert operations, we assume that for any new row that is being inserted into a table, the id would be null to successfully save into our database. The id will be generated for us.

What if we provide an id which does not exist?

If we want to store data as new record with the given id, we can try as shown here.

e.g.

{
   "id": 40,
   "description": "IPhone",
   "price": 500.95
}

We will see this exception.

 org.springframework.dao.TransientDataAccessResourceException: Failed to update table [product]. Row with Id [40] does not exist.
    at org.springframework.data.r2dbc.core.R2dbcEntityTemplate.lambda$update$5(R2dbcEntityTemplate.java:402) ~[spring-data-r2dbc-1.1.0.RC1.jar:1.1.0.RC1]
    Suppressed: reactor.core.publisher.FluxOnAssembly$OnAssemblyException:
Error has been observed at the following site(s):
    |_ checkpoint ⇢ Handler com.vinsguru.reactive.r2dbc.controller.ProductController#upsertProduct(Product) [DispatcherHandler]
    |_ checkpoint ⇢ HTTP POST "/product/save" [ExceptionHandlingWebHandler]

This is because we are trying to save a new product. The id field should be null. If it is present, Spring expects the given id to be present in the DB. So we can not insert a new record with the given id. But We can fix this by implementing the Persistable interface. If the isNew method returns new, R2DBC inserts the record with the given id.

@Data
@ToString
public class Product implements Persistable<Integer> {

    @Id
    private Integer id;
    private String description;
    private Double price;

    @Transient
    private boolean newProduct;

    @Override
    @Transient
    public boolean isNew() {
        return this.newProduct || id == null;
    }

    public Product setAsNew(){
        this.newProduct = true;
        return this;
    }

}

Links to this note