spring-projects / spring-data-relational

Spring Data Relational. Home of Spring Data JDBC and Spring Data R2DBC.
https://spring.io/projects/spring-data-jdbc
Apache License 2.0
771 stars 346 forks source link

Entity with nested entity using @Embedded - nested entity not persisted #1565

Closed rdehuyss closed 4 months ago

rdehuyss commented 1 year ago

Hi there,

I'm currently creating an app with Spring Boot and Spring Data JDBC. When I use the @Embedded for a nested entity, the nested object is not persisted. For entities that have all data in the table, everything is returned correctly. (e.g. if I debug the test and do companyRepository.findAll(), the Company objects that have been persisted via data.sql do have an Address).

I'm using:

Below a reproducible test case:

schema.sql

drop table if exists companies;
create table companies (
                        "id" uuid PRIMARY KEY,
                        "version" int,
                        "name" varchar not null,
                        "vat_number" varchar,
                        "address.first_line" varchar,
                        "address.second_line" varchar,
                        "address.third_line" varchar,
                        "address.country" varchar
);

data.sql

insert into companies("id", "version", "name", "vat_number", "address.first_line", "address.second_line", "address.third_line", "address.country") values ('8f19401a-e6f1-4a73-9244-464a2ad2f69a', 1, 'Company 1', 'BE0123456', 'Line 1', 'Line 2', null, 'BE');
insert into companies("id", "version", "name", "vat_number", "address.first_line", "address.second_line", "address.third_line", "address.country") values ('8f19401a-e6f1-4a73-9244-464a2ad2f69b', 1, 'Company 2', 'BE0123457', 'Line 1', 'Line 2', null, 'BE');

Company record

@Table(name = "companies")
public record Company (
        @Id UUID id,
        @Version int version,
        String name,
        String vatNumber,
        @Embedded(onEmpty = Embedded.OnEmpty.USE_NULL, prefix = "address.") Address address
) {
    public Company(String name, String vatNumber, Address address) {
        this(UUID.randomUUID(), 0, name, vatNumber, address);
    }

    public Company(String name, Address address) {
        this(UUID.randomUUID(), 0, name, null, address);
    }
}

Address record

public record Address(String firstLine, String secondLine, String thirdLine, String country) {

    public Address(String firstLine, String secondLine, String country) {
        this(firstLine, secondLine, null, country);
    }
}

CompanyRepository

@Repository
public interface CompanyRepository extends CrudRepository<Company, UUID> {

    Company getById(UUID id);
}

Repository Test

@SpringBootTest
class CompanyRepositoryTest {

    @Autowired
    CompanyRepository companyRepository;

    @Test
    public void saveAndGetCompany() {
        Company company = new Company("Other company", "BE98765", new Address("First Line", "Second Line", "BE"));
        companyRepository.save(company);
        Company actualCompany = companyRepository.getById(company.id());

        assertNotNull(actualCompany.address());
    }
}
rdehuyss commented 1 year ago

After further investigation, the issue is apparently the prefix = "address." with a dot. If the dot is changed to an underscore (prefix = "address_"), it works.

So, I don't know whether this is intended behaviour?

schauder commented 1 year ago

This is most certainly not the intended behaviour. Do you get an exception, or anything?

rdehuyss commented 1 year ago

No - that's why I thought to report it.

schauder commented 4 months ago

Thanks, that's fixed.