Fall back to canonical constructor in constructor resolution when using Java Records.
We now fall back to the canonical constructor of records when we cannot disambiguate which constructor to use. Also, reflect the Kotlin persistence creator mechanism. Closes #2625 Original pull request: #2694.
This commit is contained in:
@@ -20,6 +20,7 @@ import static org.assertj.core.api.Assertions.*;
|
||||
import lombok.Value;
|
||||
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import org.springframework.data.mapping.context.SampleMappingContext;
|
||||
import org.springframework.data.mapping.context.SamplePersistentProperty;
|
||||
import org.springframework.data.mapping.model.EntityInstantiators;
|
||||
@@ -44,8 +45,7 @@ class InstantiationAwarePersistentPropertyAccessorUnitTests {
|
||||
var sample = new Sample("Dave", "Matthews", 42);
|
||||
|
||||
PersistentPropertyAccessor<Sample> wrapper = new InstantiationAwarePropertyAccessor<>(sample,
|
||||
entity::getPropertyAccessor,
|
||||
instantiators);
|
||||
entity::getPropertyAccessor, instantiators);
|
||||
|
||||
wrapper.setProperty(entity.getRequiredPersistentProperty("firstname"), "Oliver August");
|
||||
|
||||
@@ -71,10 +71,38 @@ class InstantiationAwarePersistentPropertyAccessorUnitTests {
|
||||
assertThat(wrapper.getBean()).isEqualTo(new Sample("Oliver August", "Heisenberg", 42));
|
||||
}
|
||||
|
||||
@Test // GH-2625
|
||||
void shouldSetPropertyOfRecordUsingCanonicalConstructor() {
|
||||
|
||||
var instantiators = new EntityInstantiators();
|
||||
var context = new SampleMappingContext();
|
||||
|
||||
PersistentEntity<Object, SamplePersistentProperty> entity = context
|
||||
.getRequiredPersistentEntity(WithSingleArgConstructor.class);
|
||||
|
||||
var bean = new WithSingleArgConstructor(42L, "Dave");
|
||||
|
||||
PersistentPropertyAccessor<WithSingleArgConstructor> wrapper = new InstantiationAwarePropertyAccessor<>(bean,
|
||||
entity::getPropertyAccessor, instantiators);
|
||||
|
||||
wrapper.setProperty(entity.getRequiredPersistentProperty("name"), "Oliver August");
|
||||
wrapper.setProperty(entity.getRequiredPersistentProperty("id"), 41L);
|
||||
|
||||
assertThat(wrapper.getBean()).isEqualTo(new WithSingleArgConstructor(41L, "Oliver August"));
|
||||
}
|
||||
|
||||
@Value
|
||||
static class Sample {
|
||||
|
||||
String firstname, lastname;
|
||||
int age;
|
||||
}
|
||||
|
||||
public record WithSingleArgConstructor(Long id, String name) {
|
||||
|
||||
public WithSingleArgConstructor(String name) {
|
||||
this(null, name);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -26,6 +26,7 @@ import java.util.Iterator;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.springframework.beans.factory.annotation.Value;
|
||||
import org.springframework.data.annotation.PersistenceConstructor;
|
||||
import org.springframework.data.annotation.PersistenceCreator;
|
||||
import org.springframework.data.mapping.PreferredConstructorDiscovererUnitTests.Outer.Inner;
|
||||
import org.springframework.data.mapping.model.BasicPersistentEntity;
|
||||
import org.springframework.data.mapping.model.PreferredConstructorDiscoverer;
|
||||
@@ -149,6 +150,34 @@ class PreferredConstructorDiscovererUnitTests<P extends PersistentProperty<P>> {
|
||||
});
|
||||
}
|
||||
|
||||
@Test // GH-2332
|
||||
void detectsCanonicalRecordConstructor() {
|
||||
|
||||
assertThat(PreferredConstructorDiscoverer.discover(RecordWithSingleArgConstructor.class)).satisfies(ctor -> {
|
||||
|
||||
assertThat(ctor.getParameters()).hasSize(2);
|
||||
assertThat(ctor.getParameters().get(0).getRawType()).isEqualTo(Long.class);
|
||||
assertThat(ctor.getParameters().get(1).getRawType()).isEqualTo(String.class);
|
||||
});
|
||||
|
||||
assertThat(PreferredConstructorDiscoverer.discover(RecordWithNoArgConstructor.class)).satisfies(ctor -> {
|
||||
|
||||
assertThat(ctor.getParameters()).hasSize(2);
|
||||
assertThat(ctor.getParameters().get(0).getRawType()).isEqualTo(Long.class);
|
||||
assertThat(ctor.getParameters().get(1).getRawType()).isEqualTo(String.class);
|
||||
});
|
||||
}
|
||||
|
||||
@Test // GH-2332
|
||||
void detectsAnnotatedRecordConstructor() {
|
||||
|
||||
assertThat(PreferredConstructorDiscoverer.discover(RecordWithPersistenceCreator.class)).satisfies(ctor -> {
|
||||
|
||||
assertThat(ctor.getParameters()).hasSize(1);
|
||||
assertThat(ctor.getParameters().get(0).getRawType()).isEqualTo(String.class);
|
||||
});
|
||||
}
|
||||
|
||||
static class SyntheticConstructor {
|
||||
@PersistenceConstructor
|
||||
private SyntheticConstructor(String x) {}
|
||||
@@ -227,5 +256,28 @@ class PreferredConstructorDiscovererUnitTests<P extends PersistentProperty<P>> {
|
||||
@Target(ElementType.PARAMETER)
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
@Value("${hello-world}")
|
||||
@interface MyValue {}
|
||||
@interface MyValue {
|
||||
}
|
||||
|
||||
public record RecordWithSingleArgConstructor(Long id, String name) {
|
||||
|
||||
public RecordWithSingleArgConstructor(String name) {
|
||||
this(null, name);
|
||||
}
|
||||
}
|
||||
|
||||
public record RecordWithNoArgConstructor(Long id, String name) {
|
||||
|
||||
public RecordWithNoArgConstructor(String name) {
|
||||
this(null, null);
|
||||
}
|
||||
}
|
||||
|
||||
public record RecordWithPersistenceCreator(Long id, String name) {
|
||||
|
||||
@PersistenceCreator
|
||||
public RecordWithPersistenceCreator(String name) {
|
||||
this(null, name);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user