spring-data-relational icon indicating copy to clipboard operation
spring-data-relational copied to clipboard

Update domain model with generated non-id fields

Open romus opened this issue 4 years ago • 15 comments

Versions:

  • Spring boot 2.3.1.RELEASE
  • spring-data-r2dbc 1.1.1.RELEASE
  • r2dbc-postgresql 0.8.3.RELEASE

Current Behavior check_create_at_ret table has a column created_at with a default value.

create table check_create_at_ret
(
    id         bigint generated by default as identity
        constraint check_create_at_ret_pkey primary key,
    created_at timestamp default now() not null,
    status     varchar(64)
);

But after saving the new entity, the value that is set at the database level is not returned.

Example:

@Data
@NoArgsConstructor
@AllArgsConstructor
@Accessors(chain = true)
public class CheckCreateAtRet {

    @Id
    private Long id;

    private String status;

    private LocalDateTime createdAt;
    
}
public interface CheckCreateAtRetRepo extends ReactiveCrudRepository<CheckCreateAtRet, Long> {
}
// ...
private final CheckCreateAtRetRepo checkCreateAtRetRepo;

public void save() {
        checkCreateAtRetRepo.save(new CheckCreateAtRet().setStatus("Status123"))
                .doOnNext(entity -> System.out.println(entity.getCreatedAt()))
                .subscribe();
}
// ...

Null will be printed

romus avatar Sep 09 '20 21:09 romus

Thanks for report. That's a duplicate of spring-projects/spring-data-r2dbc#440/#433. Can you retest against the latest snapshots?

mp911de avatar Sep 10 '20 06:09 mp911de

Thank you for reply!

But I was able to reproduce the behavior on version 1.2.0-SNAPSHOT Demo app: https://github.com/romus/r2dbc-demo

romus avatar Sep 10 '20 19:09 romus

Thanks for the sample. I somehow was sidetracked because we had an issue where auditing and the created date was not populated. This case is different and it was never really considered to be working except for auto-generated Id's.

Postgres echo's the inserted row which allows consuming the generated fields.

mp911de avatar Sep 11 '20 06:09 mp911de

Thanks.

romus avatar Sep 12 '20 10:09 romus

I'm facing the same issue and would like to add that also the default values for fields are not populated after save/update

alesikov avatar Nov 13 '20 10:11 alesikov

Hi all,

thee is a temporary solution. It possible to wire a custom query:

@Query("INSERT INTO table (attr1,attr2 ) VALUES (:attr1, :attr1) RETURNING *") Mono<Entity> create(attr1, Uattr1);

the following returning all clause is introduced: RETURNING *.

kzvankovich avatar Dec 31 '21 12:12 kzvankovich

any updates on this? It's still relevant and would be great to have a solution for this than providing workarounds.

energy2522 avatar Jun 25 '22 11:06 energy2522

This issue needs to be addressed in Spring Data Relational first.

mp911de avatar Jun 27 '22 06:06 mp911de

@mp911de is there any issue about it on Spring Data Relational?

cemo avatar Jan 20 '23 18:01 cemo

Hi! there's some solution about this issue?

viniciusrd10 avatar Mar 15 '23 10:03 viniciusrd10

See #917

schauder avatar Sep 01 '23 11:09 schauder

The best solution I currently have for this is just adding an additional .findBy repository call after each insert/update. I'm not a fan of having to write a custom query for every insert/update as it significantly reduces the value of the built in springframework data repository. The downside of using the .findBy approach I suggested is that you will be hitting the database twice. Both workarounds suggested pollute the codebase and will need refactoring when this issue is fixed.

Had I known this was an issue from the start I would have likely just rolled a non reactive CrudRepository. The worst part about this issue is how much this issue negatively impacts readability and/or performance of your application.

Warfront1 avatar Sep 25 '23 19:09 Warfront1

This behavior is rather baffling. If the returned data from save() doesn't actually come from the database, it would make a lot more sense to have the return value be a Void type, as it is it's highly misleading and unintuitive. We already have access to the argument if we wanted to use that.

It also seems like the ID return doesn't work for certain types and certain databases. With postgres and r2dbc drivers, setting it to a UUID gives you back an entity with a null id, which makes this pretty much unusable.

CREATE TABLE broken_entity
(
    id UUID PRIMARY KEY DEFAULT gen_random_uuid()
);

  public class BrokenEntity {
      @Id
      // Will be populated by database default value
      UUID id;
  }

org.springframewoork.boot:spring-boot-starter-data-r2dbc:2.7.17 io.r2dbc:r2dbc-pool:0.9.2.RELEASE org.postgresql:postgresql:42.3.8 org.postgresql:r2dbc-postgresql:0.9.2.RELEASE

Dwight-D avatar Nov 16 '23 11:11 Dwight-D

@Dwight-D The behaviour you describe with R2DBC is unrelated to this topic and sounds like a bug. Please create a separate issue for it.

schauder avatar Nov 16 '23 11:11 schauder

@Dwight-D The behaviour you describe with R2DBC is unrelated to this topic and sounds like a bug. Please create a separate issue for it.

Got it, thanks. Either way, I think it would be resolved if the save() call returned the actual data for the entire entity, which I think is the only sane behavior here from a user perspective.

Dwight-D avatar Nov 16 '23 11:11 Dwight-D