Don't try to write non-writeable properties.

Original Pull Request #2249
Closes #2230
This commit is contained in:
Peter-Josef Meisch 2022-08-04 08:04:19 +02:00 committed by GitHub
parent 6ad449c9f4
commit acf02a1dc9
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
7 changed files with 102 additions and 7 deletions

View File

@ -465,7 +465,7 @@ public abstract class AbstractElasticsearchTemplate implements ElasticsearchOper
ElasticsearchPersistentProperty idProperty = persistentEntity.getIdProperty(); ElasticsearchPersistentProperty idProperty = persistentEntity.getIdProperty();
// Only deal with text because ES generated Ids are strings! // Only deal with text because ES generated Ids are strings!
if (indexedObjectInformation.getId() != null && idProperty != null if (indexedObjectInformation.getId() != null && idProperty != null && idProperty.isWritable()
&& idProperty.getType().isAssignableFrom(String.class)) { && idProperty.getType().isAssignableFrom(String.class)) {
propertyAccessor.setProperty(idProperty, indexedObjectInformation.getId()); propertyAccessor.setProperty(idProperty, indexedObjectInformation.getId());
} }

View File

@ -259,7 +259,7 @@ abstract public class AbstractReactiveElasticsearchTemplate
ElasticsearchPersistentProperty idProperty = persistentEntity.getIdProperty(); ElasticsearchPersistentProperty idProperty = persistentEntity.getIdProperty();
// Only deal with text because ES generated Ids are strings! // Only deal with text because ES generated Ids are strings!
if (indexedObjectInformation.getId() != null && idProperty != null if (indexedObjectInformation.getId() != null && idProperty != null && idProperty.isWritable()
&& idProperty.getType().isAssignableFrom(String.class)) { && idProperty.getType().isAssignableFrom(String.class)) {
propertyAccessor.setProperty(idProperty, indexedObjectInformation.getId()); propertyAccessor.setProperty(idProperty, indexedObjectInformation.getId());
} }

View File

@ -342,7 +342,7 @@ public class MappingElasticsearchConverter
PersistentPropertyAccessor<R> propertyAccessor = new ConvertingPropertyAccessor<>( PersistentPropertyAccessor<R> propertyAccessor = new ConvertingPropertyAccessor<>(
targetEntity.getPropertyAccessor(result), conversionService); targetEntity.getPropertyAccessor(result), conversionService);
// Only deal with String because ES generated Ids are strings ! // Only deal with String because ES generated Ids are strings !
if (idProperty != null && idProperty.getType().isAssignableFrom(String.class)) { if (idProperty != null && idProperty.isWritable() && idProperty.getType().isAssignableFrom(String.class)) {
propertyAccessor.setProperty(idProperty, document.getId()); propertyAccessor.setProperty(idProperty, document.getId());
} }
} }
@ -406,7 +406,7 @@ public class MappingElasticsearchConverter
for (ElasticsearchPersistentProperty prop : entity) { for (ElasticsearchPersistentProperty prop : entity) {
if (entity.isCreatorArgument(prop) || !prop.isReadable()) { if (entity.isCreatorArgument(prop) || !prop.isReadable() || !prop.isWritable()) {
continue; continue;
} }

View File

@ -54,7 +54,9 @@ import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.dao.DataAccessException; import org.springframework.dao.DataAccessException;
import org.springframework.dao.InvalidDataAccessApiUsageException; import org.springframework.dao.InvalidDataAccessApiUsageException;
import org.springframework.dao.OptimisticLockingFailureException; import org.springframework.dao.OptimisticLockingFailureException;
import org.springframework.data.annotation.AccessType;
import org.springframework.data.annotation.Id; import org.springframework.data.annotation.Id;
import org.springframework.data.annotation.ReadOnlyProperty;
import org.springframework.data.annotation.Version; import org.springframework.data.annotation.Version;
import org.springframework.data.domain.PageRequest; import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable; import org.springframework.data.domain.Pageable;
@ -3705,6 +3707,21 @@ public abstract class ElasticsearchIntegrationTests implements NewElasticsearchC
} }
} }
@Test // #2230
@DisplayName("should work with readonly id")
void shouldWorkWithReadonlyId() {
ReadonlyIdEntity entity = new ReadonlyIdEntity();
entity.setPart1("foo");
entity.setPart2("bar");
operations.save(entity);
ReadonlyIdEntity readEntity = operations.get(entity.getId(), ReadonlyIdEntity.class);
assertThat(readEntity.getPart1()).isEqualTo(entity.getPart1());
assertThat(readEntity.getPart2()).isEqualTo(entity.getPart2());
}
@Document(indexName = "#{@indexNameProvider.indexName()}") @Document(indexName = "#{@indexNameProvider.indexName()}")
private static class SampleEntityUUIDKeyed { private static class SampleEntityUUIDKeyed {
@Nullable @Nullable
@ -4450,5 +4467,36 @@ public abstract class ElasticsearchIntegrationTests implements NewElasticsearchC
+ '}'; + '}';
} }
} }
@Document(indexName = "#{@indexNameProvider.indexName()}-readonly-id")
static class ReadonlyIdEntity {
@Field(type = FieldType.Keyword) private String part1;
@Field(type = FieldType.Keyword) private String part2;
@Id
@ReadOnlyProperty
@AccessType(AccessType.Type.PROPERTY)
public String getId() {
return part1 + '-' + part2;
}
public String getPart1() {
return part1;
}
public void setPart1(String part1) {
this.part1 = part1;
}
public String getPart2() {
return part2;
}
public void setPart2(String part2) {
this.part2 = part2;
}
}
// endregion // endregion
} }

View File

@ -50,7 +50,9 @@ import org.skyscreamer.jsonassert.JSONAssert;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.dao.DataAccessException; import org.springframework.dao.DataAccessException;
import org.springframework.dao.OptimisticLockingFailureException; import org.springframework.dao.OptimisticLockingFailureException;
import org.springframework.data.annotation.AccessType;
import org.springframework.data.annotation.Id; import org.springframework.data.annotation.Id;
import org.springframework.data.annotation.ReadOnlyProperty;
import org.springframework.data.annotation.Version; import org.springframework.data.annotation.Version;
import org.springframework.data.domain.PageRequest; import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable; import org.springframework.data.domain.Pageable;
@ -1161,6 +1163,23 @@ public abstract class ReactiveElasticsearchIntegrationTests implements NewElasti
.verifyComplete(); .verifyComplete();
} }
@Test // #2230
@DisplayName("should work with readonly id")
void shouldWorkWithReadonlyId() {
ReadonlyIdEntity entity = new ReadonlyIdEntity();
entity.setPart1("foo");
entity.setPart2("bar");
operations.save(entity).block();
operations.get(entity.getId(), ReadonlyIdEntity.class) //
.as(StepVerifier::create) //
.assertNext(readEntity -> { //
assertThat(readEntity.getPart1()).isEqualTo(entity.getPart1()); //
assertThat(readEntity.getPart2()).isEqualTo(entity.getPart2()); //
}).verifyComplete();
}
// endregion // endregion
// region Helper functions // region Helper functions
@ -1494,5 +1513,35 @@ public abstract class ReactiveElasticsearchIntegrationTests implements NewElasti
+ seqNoPrimaryTerm + '}'; + seqNoPrimaryTerm + '}';
} }
} }
@Document(indexName = "#{@indexNameProvider.indexName()}-readonly-id")
static class ReadonlyIdEntity {
@Field(type = FieldType.Keyword) private String part1;
@Field(type = FieldType.Keyword) private String part2;
@Id
@ReadOnlyProperty
@AccessType(AccessType.Type.PROPERTY)
public String getId() {
return part1 + '-' + part2;
}
public String getPart1() {
return part1;
}
public void setPart1(String part1) {
this.part1 = part1;
}
public String getPart2() {
return part2;
}
public void setPart2(String part2) {
this.part2 = part2;
}
}
// endregion // endregion
} }

View File

@ -241,7 +241,7 @@ abstract class CallbackIntegrationTests {
@Id private String id; @Id private String id;
@Nullable private String text; @Nullable private String text;
@ReadOnlyProperty // @ReadOnlyProperty
@Nullable private String className; @Nullable private String className;
@Nullable @Nullable

View File

@ -27,7 +27,6 @@ import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Configuration;
import org.springframework.data.annotation.Id; import org.springframework.data.annotation.Id;
import org.springframework.data.annotation.ReadOnlyProperty;
import org.springframework.data.elasticsearch.annotations.Document; import org.springframework.data.elasticsearch.annotations.Document;
import org.springframework.data.elasticsearch.core.ReactiveElasticsearchOperations; import org.springframework.data.elasticsearch.core.ReactiveElasticsearchOperations;
import org.springframework.data.elasticsearch.core.ReactiveIndexOperations; import org.springframework.data.elasticsearch.core.ReactiveIndexOperations;
@ -119,7 +118,6 @@ public abstract class ReactiveCallbackIntegrationTests {
@Id private String id; @Id private String id;
private String text; private String text;
@ReadOnlyProperty
@Nullable private String className; @Nullable private String className;
public SampleEntity(String id, String text) { public SampleEntity(String id, String text) {