spring-projects / spring-data-commons

Spring Data Commons. Interfaces and code shared between the various datastore specific implementations.
https://spring.io/projects/spring-data
Apache License 2.0
768 stars 666 forks source link

Ignore `@Transient` properties in constructors #2942

Open sunny-chung opened 11 months ago

sunny-chung commented 11 months ago

This is a feature request. Currently querying an entity like this would fail:

@Table(name = "chat__channel")
data class ChatChannel(
    val name: String,
    @Transient val creationRequestId: String? = null
) : BaseEntity()

with exception:

java.lang.IllegalStateException: Required property creationRequestId not found for class com.example.entity.ChatChannel
    at org.springframework.data.mapping.PersistentEntity.getRequiredPersistentProperty(PersistentEntity.java:190) ~[spring-data-commons-3.1.2.jar!/:3.1.2]
    Suppressed: reactor.core.publisher.FluxOnAssembly$OnAssemblyException:
Error has been observed at the following site(s):
    *__checkpoint ⇢ Handler com.example.api.ChannelApi#list(String, Continuation) [DispatcherHandler]
Original Stack Trace:
        at org.springframework.data.mapping.PersistentEntity.getRequiredPersistentProperty(PersistentEntity.java:190) ~[spring-data-commons-3.1.2.jar!/:3.1.2]
        at org.springframework.data.r2dbc.convert.MappingR2dbcConverter$RowParameterValueProvider.getParameterValue(MappingR2dbcConverter.java:715) ~[spring-data-r2dbc-3.1.2.jar!/:3.1.2]
        at org.springframework.data.mapping.model.SpELExpressionParameterValueProvider.getParameterValue(SpELExpressionParameterValueProvider.java:49) ~[spring-data-commons-3.1.2.jar!/:3.1.2]
        at org.springframework.data.relational.core.conversion.BasicRelationalConverter$ConvertingParameterValueProvider.getParameterValue(BasicRelationalConverter.java:298) ~[spring-data-relational-3.1.2.jar!/:3.1.2]
        at org.springframework.data.mapping.model.KotlinClassGeneratingEntityInstantiator$DefaultingKotlinClassInstantiatorAdapter.extractInvocationArguments(KotlinClassGeneratingEntityInstantiator.java:222) ~[spring-data-commons-3.1.2.jar!/:3.1.2]
        at org.springframework.data.mapping.model.KotlinClassGeneratingEntityInstantiator$DefaultingKotlinClassInstantiatorAdapter.createInstance(KotlinClassGeneratingEntityInstantiator.java:196) ~[spring-data-commons-3.1.2.jar!/:3.1.2]
        at org.springframework.data.mapping.model.ClassGeneratingEntityInstantiator.createInstance(ClassGeneratingEntityInstantiator.java:98) ~[spring-data-commons-3.1.2.jar!/:3.1.2]
        at org.springframework.data.relational.core.conversion.BasicRelationalConverter.createInstance(BasicRelationalConverter.java:136) ~[spring-data-relational-3.1.2.jar!/:3.1.2]
        at org.springframework.data.r2dbc.convert.MappingR2dbcConverter.createInstance(MappingR2dbcConverter.java:328) ~[spring-data-r2dbc-3.1.2.jar!/:3.1.2]
        at org.springframework.data.r2dbc.convert.MappingR2dbcConverter.read(MappingR2dbcConverter.java:120) ~[spring-data-r2dbc-3.1.2.jar!/:3.1.2]
        at org.springframework.data.r2dbc.convert.MappingR2dbcConverter.read(MappingR2dbcConverter.java:115) ~[spring-data-r2dbc-3.1.2.jar!/:3.1.2]
        at org.springframework.data.r2dbc.convert.EntityRowMapper.apply(EntityRowMapper.java:42) ~[spring-data-r2dbc-3.1.2.jar!/:3.1.2]
        at org.springframework.data.r2dbc.convert.EntityRowMapper.apply(EntityRowMapper.java:29) ~[spring-data-r2dbc-3.1.2.jar!/:3.1.2]
        at io.asyncer.r2dbc.mysql.MySqlResult.lambda$map$1(MySqlResult.java:94) ~[r2dbc-mysql-1.0.2.jar!/:1.0.2]

...

Although there are many workarounds, it would be better if fields marked @Transient and have a default value in the constructor could be "ignored", so that we do not have to add another constructor to handle this use case.

mp911de commented 11 months ago

Constructor arguments map to properties and @Transient is applied from the property declaration. Let me take your request to the team.

mp911de commented 9 months ago

We consider adding support for @Transient properties in constructors. Record components could also be annotated with the @Transient annotation to allow record construction. While this can be useful, we recommend using the @Value annotation to use SpEL expressions to determine a useful value.