postgresqlone-to-manymicronautr2dbc

Micronaut R2DBC Parent Child Relationship Parent ID not getting inserted into child (One to Many)


I am new to R2DBC and I have a fairly standard parent child relationship Person / Address and when attempting to save a person object with an address both the person and the address get saved but the Person ID is not getting saved to Address table.
I am using Postgres with Micronaut and R2DBC. The following is the code

Base Fields:

@Data
@Introspected
@Serdeable
@MappedEntity
public class BaseFields {
    @GeneratedValue
    @Id
    private Long id;
    private String note;
    private String recordType;

Person:

@Data
@Introspected
@Serdeable
@MappedEntity
public class Person extends BaseFields{
    private String firstName;
    private String lastName;
    private String phoneNumber;

    @JoinColumn(name = "personId")
    @Relation(value = Relation.Kind.ONE_TO_MANY, cascade = Relation.Cascade.ALL)
    private Set<Address> addresses;
}

Address:

@Data
@Introspected
@Serdeable
@MappedEntity
public class Address extends BaseFields {
    private String street;
    private String street2;
    private String suite;
    private String city;
    private String stateProvince;
    private String country;
    private String postalCode;
    private Boolean active;

    private Long personId;

}

PersonRepository:

@Introspected
@R2dbcRepository(dialect = Dialect.POSTGRES)
public interface PersonRepository extends ReactiveStreamsCrudRepository<Person, Long>{
    @NonNull
    @Override
    @Join(value = "addresses", type = Join.Type.FETCH)
    Flux<Person> findAll();

    @NonNull
    @Override
    @Join(value = "addresses", type = Join.Type.FETCH)
    Mono<Person> findById(@NonNull @NotNull Long id);

}

PersonController:

@Controller("/person")
public class PersonController {
    private final PersonRepository personRepository;
    private final PersonService personService;

    PersonController(PersonRepository personRepository, PersonService personService) {
        this.personRepository = personRepository;
        this.personService = personService;

    @SingleResult
    @Post
    Mono<Person> create(@Valid @Body Person person){
//        return personService.createPerson(person);
          return Mono.from(personRepository.save(person));
    }
}

Postman Body and result:

{
        "firstName": "Kelly",
        "lastName": "Kingster",
        "phoneNumber": "451.881.9745",
        "addresses": [
            {
                "street": "155379 W12th Street",
                "city": "Fargo",
                "stateProvince": "ND",
                "country": "USA",
                "postalCode": "44577",
                "active": true
            }
        ]
}

Result:

{
    "id": 11,
    "firstName": "Kelly",
    "lastName": "Kingster",
    "phoneNumber": "451.881.9745",
    "addresses": [
        {
            "id": 12,
            "street": "155379 W12th Street",
            "city": "Fargo",
            "stateProvince": "ND",
            "country": "USA",
            "postalCode": "44577",
            "active": true
        }
    ]
}

Both records are inserted but there is no person_id on the address record

"id","street","street2","suite","city","state_province","country","postal_code","active","person_id","record_type","note","created","modified"

12,"155379 W12th Street",NULL,NULL,"Fargo","ND","USA","44577",True,NULL,NULL,NULL,"2024-07-09 15:22:20.637259","2024-07-09 15:22:20.637259"

Solution

  • Try to update the annotation on your entities like this.

    
    public class Person ...{
    
        // ...
        @Relation(value = Relation.Kind.ONE_TO_MANY, cascade = Relation.Cascade.ALL)
        private Set<Address> addresses;
    }
    
    
    public class Address...{
    
        @Relation(value = Relation.Kind.MANY_TO_ONE)
        @JoinColumn("person_id") // move here
        private Person person;
    
    }
    

    Check my Micronaut R2dbc example project here which demos one-to-many relations.

    BTW: Micronaut Data supports JPA annotations in Micronaut data Jdbc/R2dbc, you can use JPA annotations directly if you are more familiar with it.