Skip to content

@Table class supports Record (or AllArgsConstructor), but does not support using it with @Transient. #3256

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
seminchoi opened this issue Mar 16, 2025 · 1 comment
Labels
for: stackoverflow A question that's better suited to stackoverflow.com

Comments

@seminchoi
Copy link

seminchoi commented Mar 16, 2025

When using Persistable with a record class in an R2DBC Data Repository, I found that the record does not work properly with the @Transient annotation.

Here is a sample code:

@Table("sample")
@Builder
public record SampleRecord(
        @Id
        UUID id,

        @Transient
        boolean isNew
) implements Persistable<UUID> {
    @Override
    public UUID getId() {
        return id;
    }

    @Override
    public boolean isNew() {
        return isNew;
    }
}

public interface SampleRecordRepository extends R2dbcRepository<SampleRecord, UUID> {
}

And the test code:

@SpringBootTest
class Simpler2dbcPersistableExampleApplicationTests {
    @Autowired
    SampleRecordRepository sampleRecordRepository;

    @Test
    void recordTest() {
        UUID sampleId = UUID.randomUUID();

        SampleRecord sample = SampleRecord.builder()
                .id(sampleId)
                .isNew(true)
                .build();

        sampleRecordRepository.save(sample)
                .then(sampleRecordRepository.findById(sampleId))
                .block();
    }
}

Running this test produces the following error:

No property isNew found on entity class com.sem.simpler2dbcpersistableexample.Sample to bind constructor parameter to
org.springframework.data.mapping.MappingException: No property isNew found on entity class com.sem.simpler2dbcpersistableexample.Sample to bind constructor parameter to
	at org.springframework.data.mapping.model.PersistentEntityParameterValueProvider.getParameterValue(PersistentEntityParameterValueProvider.java:69)
	at org.springframework.data.relational.core.conversion.MappingRelationalConverter$ConvertingParameterValueProvider.getParameterValue(MappingRelationalConverter.java:1244)
	at org.springframework.data.mapping.model.ValueExpressionParameterValueProvider.getParameterValue(ValueExpressionParameterValueProvider.java:56)
	at org.springframework.data.mapping.model.ClassGeneratingEntityInstantiator.extractInvocationArguments(ClassGeneratingEntityInstantiator.java:301)
	at org.springframework.data.mapping.model.ClassGeneratingEntityInstantiator$EntityInstantiatorAdapter.createInstance(ClassGeneratingEntityInstantiator.java:273)
	at org.springframework.data.mapping.model.ClassGeneratingEntityInstantiator.createInstance(ClassGeneratingEntityInstantiator.java:98)
	at org.springframework.data.relational.core.conversion.MappingRelationalConverter.read(MappingRelationalConverter.java:462)
	at org.springframework.data.relational.core.conversion.MappingRelationalConverter.readAggregate(MappingRelationalConverter.java:357)
	at org.springframework.data.relational.core.conversion.MappingRelationalConverter.readAggregate(MappingRelationalConverter.java:320)
	at org.springframework.data.relational.core.conversion.MappingRelationalConverter.read(MappingRelationalConverter.java:307)
	at org.springframework.data.relational.core.conversion.MappingRelationalConverter.project(MappingRelationalConverter.java:197)
	at 
...

After debugging the issue, I found that when creating the entity without using the default constructor, no additional actions are performed, such as injecting null values or default values, into fields annotated with @Transient.
Therefore, this issue does not occur only with records, but also with classes that only have a constructor that takes a field annotated with @Transient as an argument.

The issue can be reproduced at https://github.com/seminchoi/r2dbc-transient-issue

If this is supported, I believe it could be useful with compact constructor of Record.
So, I was wondering if this behavior is intentional or if not, there are any plans to support it.
Additionally, I would like to know if I can contribute to fixing this issue. If so, could you provide me with some guidance on which packages or classes I should check and modify?

@spring-projects-issues spring-projects-issues added the status: waiting-for-triage An issue we've not yet triaged label Mar 16, 2025
@seminchoi seminchoi changed the title @Table Class supports Record (or AllArgsConstructor), but does not support @Transient. @Table class supports Record (or AllArgsConstructor), but does not support using it with @Transient. Mar 16, 2025
@mp911de
Copy link
Member

mp911de commented Mar 17, 2025

Spring Data must summon a value for isNew from somewhere and so you cannot just use a full constructor. Please use one without the isNew argument and annotate it with @PersistenceCreator if you have more than one constructor.

@mp911de mp911de closed this as not planned Won't fix, can't repro, duplicate, stale Mar 17, 2025
@mp911de mp911de added for: stackoverflow A question that's better suited to stackoverflow.com and removed status: waiting-for-triage An issue we've not yet triaged labels Mar 17, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
for: stackoverflow A question that's better suited to stackoverflow.com
Projects
None yet
Development

No branches or pull requests

3 participants