mirror of
https://github.com/spring-projects/spring-data-elasticsearch.git
synced 2025-05-31 09:12:11 +00:00
Improve handling of immutable classes.
Original Pull Request #1801 Closes #1800
This commit is contained in:
parent
502ce0b6aa
commit
159687e241
@ -188,7 +188,7 @@ public abstract class AbstractElasticsearchTemplate implements ElasticsearchOper
|
|||||||
IndexQuery query = getIndexQuery(entityAfterBeforeConvert);
|
IndexQuery query = getIndexQuery(entityAfterBeforeConvert);
|
||||||
doIndex(query, index);
|
doIndex(query, index);
|
||||||
|
|
||||||
T entityAfterAfterSave = maybeCallbackAfterSave(entityAfterBeforeConvert, index);
|
T entityAfterAfterSave = (T) maybeCallbackAfterSave(query.getObject(), index);
|
||||||
|
|
||||||
return entityAfterAfterSave;
|
return entityAfterAfterSave;
|
||||||
}
|
}
|
||||||
@ -215,13 +215,18 @@ public abstract class AbstractElasticsearchTemplate implements ElasticsearchOper
|
|||||||
List<IndexQuery> indexQueries = Streamable.of(entities).stream().map(this::getIndexQuery)
|
List<IndexQuery> indexQueries = Streamable.of(entities).stream().map(this::getIndexQuery)
|
||||||
.collect(Collectors.toList());
|
.collect(Collectors.toList());
|
||||||
|
|
||||||
if (!indexQueries.isEmpty()) {
|
if (indexQueries.isEmpty()) {
|
||||||
List<IndexedObjectInformation> indexedObjectInformations = bulkIndex(indexQueries, index);
|
return Collections.emptyList();
|
||||||
Iterator<IndexedObjectInformation> iterator = indexedObjectInformations.iterator();
|
|
||||||
entities.forEach(entity -> updateIndexedObject(entity, iterator.next()));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return indexQueries.stream().map(IndexQuery::getObject).map(entity -> (T) entity).collect(Collectors.toList());
|
List<IndexedObjectInformation> indexedObjectInformations = bulkIndex(indexQueries, index);
|
||||||
|
Iterator<IndexedObjectInformation> iterator = indexedObjectInformations.iterator();
|
||||||
|
|
||||||
|
// noinspection unchecked
|
||||||
|
return indexQueries.stream() //
|
||||||
|
.map(IndexQuery::getObject) //
|
||||||
|
.map(entity -> (T) updateIndexedObject(entity, iterator.next())) //
|
||||||
|
.collect(Collectors.toList()); //
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -419,7 +424,9 @@ public abstract class AbstractElasticsearchTemplate implements ElasticsearchOper
|
|||||||
Assert.notNull(query.getId(), "No document id defined for MoreLikeThisQuery");
|
Assert.notNull(query.getId(), "No document id defined for MoreLikeThisQuery");
|
||||||
|
|
||||||
MoreLikeThisQueryBuilder moreLikeThisQueryBuilder = requestFactory.moreLikeThisQueryBuilder(query, index);
|
MoreLikeThisQueryBuilder moreLikeThisQueryBuilder = requestFactory.moreLikeThisQueryBuilder(query, index);
|
||||||
return search(new NativeSearchQueryBuilder().withQuery(moreLikeThisQueryBuilder).withPageable(query.getPageable()).build(), clazz, index);
|
return search(
|
||||||
|
new NativeSearchQueryBuilder().withQuery(moreLikeThisQueryBuilder).withPageable(query.getPageable()).build(),
|
||||||
|
clazz, index);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -611,7 +618,7 @@ public abstract class AbstractElasticsearchTemplate implements ElasticsearchOper
|
|||||||
}).collect(Collectors.toList());
|
}).collect(Collectors.toList());
|
||||||
}
|
}
|
||||||
|
|
||||||
protected void updateIndexedObject(Object entity, IndexedObjectInformation indexedObjectInformation) {
|
protected <T> T updateIndexedObject(T entity, IndexedObjectInformation indexedObjectInformation) {
|
||||||
|
|
||||||
ElasticsearchPersistentEntity<?> persistentEntity = elasticsearchConverter.getMappingContext()
|
ElasticsearchPersistentEntity<?> persistentEntity = elasticsearchConverter.getMappingContext()
|
||||||
.getPersistentEntity(entity.getClass());
|
.getPersistentEntity(entity.getClass());
|
||||||
@ -621,22 +628,30 @@ 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 (idProperty != null && idProperty.getType().isAssignableFrom(String.class)) {
|
if (indexedObjectInformation.getId() != null && idProperty != null
|
||||||
|
&& idProperty.getType().isAssignableFrom(String.class)) {
|
||||||
propertyAccessor.setProperty(idProperty, indexedObjectInformation.getId());
|
propertyAccessor.setProperty(idProperty, indexedObjectInformation.getId());
|
||||||
}
|
}
|
||||||
|
|
||||||
if (indexedObjectInformation.getSeqNo() != null && indexedObjectInformation.getPrimaryTerm() != null
|
if (indexedObjectInformation.getSeqNo() != null && indexedObjectInformation.getPrimaryTerm() != null
|
||||||
&& persistentEntity.hasSeqNoPrimaryTermProperty()) {
|
&& persistentEntity.hasSeqNoPrimaryTermProperty()) {
|
||||||
ElasticsearchPersistentProperty seqNoPrimaryTermProperty = persistentEntity.getSeqNoPrimaryTermProperty();
|
ElasticsearchPersistentProperty seqNoPrimaryTermProperty = persistentEntity.getSeqNoPrimaryTermProperty();
|
||||||
|
// noinspection ConstantConditions
|
||||||
propertyAccessor.setProperty(seqNoPrimaryTermProperty,
|
propertyAccessor.setProperty(seqNoPrimaryTermProperty,
|
||||||
new SeqNoPrimaryTerm(indexedObjectInformation.getSeqNo(), indexedObjectInformation.getPrimaryTerm()));
|
new SeqNoPrimaryTerm(indexedObjectInformation.getSeqNo(), indexedObjectInformation.getPrimaryTerm()));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (indexedObjectInformation.getVersion() != null && persistentEntity.hasVersionProperty()) {
|
if (indexedObjectInformation.getVersion() != null && persistentEntity.hasVersionProperty()) {
|
||||||
ElasticsearchPersistentProperty versionProperty = persistentEntity.getVersionProperty();
|
ElasticsearchPersistentProperty versionProperty = persistentEntity.getVersionProperty();
|
||||||
|
// noinspection ConstantConditions
|
||||||
propertyAccessor.setProperty(versionProperty, indexedObjectInformation.getVersion());
|
propertyAccessor.setProperty(versionProperty, indexedObjectInformation.getVersion());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// noinspection unchecked
|
||||||
|
T updatedEntity = (T) propertyAccessor.getBean();
|
||||||
|
return updatedEntity;
|
||||||
}
|
}
|
||||||
|
return entity;
|
||||||
}
|
}
|
||||||
|
|
||||||
ElasticsearchPersistentEntity<?> getRequiredPersistentEntity(Class<?> clazz) {
|
ElasticsearchPersistentEntity<?> getRequiredPersistentEntity(Class<?> clazz) {
|
||||||
@ -807,13 +822,16 @@ public abstract class AbstractElasticsearchTemplate implements ElasticsearchOper
|
|||||||
|
|
||||||
protected void updateIndexedObjectsWithQueries(List<?> queries,
|
protected void updateIndexedObjectsWithQueries(List<?> queries,
|
||||||
List<IndexedObjectInformation> indexedObjectInformations) {
|
List<IndexedObjectInformation> indexedObjectInformations) {
|
||||||
|
|
||||||
for (int i = 0; i < queries.size(); i++) {
|
for (int i = 0; i < queries.size(); i++) {
|
||||||
Object query = queries.get(i);
|
Object query = queries.get(i);
|
||||||
|
|
||||||
if (query instanceof IndexQuery) {
|
if (query instanceof IndexQuery) {
|
||||||
IndexQuery indexQuery = (IndexQuery) query;
|
IndexQuery indexQuery = (IndexQuery) query;
|
||||||
Object queryObject = indexQuery.getObject();
|
Object queryObject = indexQuery.getObject();
|
||||||
|
|
||||||
if (queryObject != null) {
|
if (queryObject != null) {
|
||||||
updateIndexedObject(queryObject, indexedObjectInformations.get(i));
|
indexQuery.setObject(updateIndexedObject(queryObject, indexedObjectInformations.get(i)));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -848,6 +866,10 @@ public abstract class AbstractElasticsearchTemplate implements ElasticsearchOper
|
|||||||
}
|
}
|
||||||
|
|
||||||
T entity = reader.read(type, document);
|
T entity = reader.read(type, document);
|
||||||
|
IndexedObjectInformation indexedObjectInformation = IndexedObjectInformation.of(
|
||||||
|
document.hasId() ? document.getId() : null, document.getSeqNo(), document.getPrimaryTerm(),
|
||||||
|
document.getVersion());
|
||||||
|
entity = updateIndexedObject(entity, indexedObjectInformation);
|
||||||
return maybeCallbackAfterConvert(entity, document, index);
|
return maybeCallbackAfterConvert(entity, document, index);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -157,9 +157,10 @@ public class ElasticsearchRestTemplate extends AbstractElasticsearchTemplate {
|
|||||||
IndexResponse indexResponse = execute(client -> client.index(request, RequestOptions.DEFAULT));
|
IndexResponse indexResponse = execute(client -> client.index(request, RequestOptions.DEFAULT));
|
||||||
|
|
||||||
Object queryObject = query.getObject();
|
Object queryObject = query.getObject();
|
||||||
|
|
||||||
if (queryObject != null) {
|
if (queryObject != null) {
|
||||||
updateIndexedObject(queryObject, IndexedObjectInformation.of(indexResponse.getId(), indexResponse.getSeqNo(),
|
query.setObject(updateIndexedObject(queryObject, IndexedObjectInformation.of(indexResponse.getId(),
|
||||||
indexResponse.getPrimaryTerm(), indexResponse.getVersion()));
|
indexResponse.getSeqNo(), indexResponse.getPrimaryTerm(), indexResponse.getVersion())));
|
||||||
}
|
}
|
||||||
|
|
||||||
return indexResponse.getId();
|
return indexResponse.getId();
|
||||||
@ -168,6 +169,7 @@ public class ElasticsearchRestTemplate extends AbstractElasticsearchTemplate {
|
|||||||
@Override
|
@Override
|
||||||
@Nullable
|
@Nullable
|
||||||
public <T> T get(String id, Class<T> clazz, IndexCoordinates index) {
|
public <T> T get(String id, Class<T> clazz, IndexCoordinates index) {
|
||||||
|
|
||||||
GetRequest request = requestFactory.getRequest(id, routingResolver.getRouting(), index);
|
GetRequest request = requestFactory.getRequest(id, routingResolver.getRouting(), index);
|
||||||
GetResponse response = execute(client -> client.get(request, RequestOptions.DEFAULT));
|
GetResponse response = execute(client -> client.get(request, RequestOptions.DEFAULT));
|
||||||
|
|
||||||
|
@ -177,8 +177,8 @@ public class ElasticsearchTemplate extends AbstractElasticsearchTemplate {
|
|||||||
|
|
||||||
Object queryObject = query.getObject();
|
Object queryObject = query.getObject();
|
||||||
if (queryObject != null) {
|
if (queryObject != null) {
|
||||||
updateIndexedObject(queryObject, IndexedObjectInformation.of(documentId, response.getSeqNo(),
|
query.setObject(updateIndexedObject(queryObject, IndexedObjectInformation.of(documentId, response.getSeqNo(),
|
||||||
response.getPrimaryTerm(), response.getVersion()));
|
response.getPrimaryTerm(), response.getVersion())));
|
||||||
}
|
}
|
||||||
|
|
||||||
return documentId;
|
return documentId;
|
||||||
|
@ -477,7 +477,6 @@ class EntityOperations {
|
|||||||
*/
|
*/
|
||||||
private static class AdaptibleMappedEntity<T> extends MappedEntity<T> implements AdaptibleEntity<T> {
|
private static class AdaptibleMappedEntity<T> extends MappedEntity<T> implements AdaptibleEntity<T> {
|
||||||
|
|
||||||
private final T bean;
|
|
||||||
private final ElasticsearchPersistentEntity<?> entity;
|
private final ElasticsearchPersistentEntity<?> entity;
|
||||||
private final ConvertingPropertyAccessor<T> propertyAccessor;
|
private final ConvertingPropertyAccessor<T> propertyAccessor;
|
||||||
private final IdentifierAccessor identifierAccessor;
|
private final IdentifierAccessor identifierAccessor;
|
||||||
@ -490,7 +489,6 @@ class EntityOperations {
|
|||||||
|
|
||||||
super(entity, identifierAccessor, propertyAccessor);
|
super(entity, identifierAccessor, propertyAccessor);
|
||||||
|
|
||||||
this.bean = bean;
|
|
||||||
this.entity = entity;
|
this.entity = entity;
|
||||||
this.propertyAccessor = propertyAccessor;
|
this.propertyAccessor = propertyAccessor;
|
||||||
this.identifierAccessor = identifierAccessor;
|
this.identifierAccessor = identifierAccessor;
|
||||||
@ -510,6 +508,11 @@ class EntityOperations {
|
|||||||
new ConvertingPropertyAccessor<>(propertyAccessor, conversionService), conversionService, routingResolver);
|
new ConvertingPropertyAccessor<>(propertyAccessor, conversionService), conversionService, routingResolver);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public T getBean() {
|
||||||
|
return propertyAccessor.getBean();
|
||||||
|
}
|
||||||
|
|
||||||
@Nullable
|
@Nullable
|
||||||
@Override
|
@Override
|
||||||
public T populateIdIfNecessary(@Nullable Object id) {
|
public T populateIdIfNecessary(@Nullable Object id) {
|
||||||
@ -584,7 +587,7 @@ class EntityOperations {
|
|||||||
@Override
|
@Override
|
||||||
public String getRouting() {
|
public String getRouting() {
|
||||||
|
|
||||||
String routing = routingResolver.getRouting(bean);
|
String routing = routingResolver.getRouting(propertyAccessor.getBean());
|
||||||
|
|
||||||
if (routing != null) {
|
if (routing != null) {
|
||||||
return routing;
|
return routing;
|
||||||
|
@ -25,12 +25,12 @@ import org.springframework.lang.Nullable;
|
|||||||
* @since 4.1
|
* @since 4.1
|
||||||
*/
|
*/
|
||||||
public class IndexedObjectInformation {
|
public class IndexedObjectInformation {
|
||||||
private final String id;
|
@Nullable private final String id;
|
||||||
@Nullable private final Long seqNo;
|
@Nullable private final Long seqNo;
|
||||||
@Nullable private final Long primaryTerm;
|
@Nullable private final Long primaryTerm;
|
||||||
@Nullable private final Long version;
|
@Nullable private final Long version;
|
||||||
|
|
||||||
private IndexedObjectInformation(String id, @Nullable Long seqNo, @Nullable Long primaryTerm,
|
private IndexedObjectInformation(@Nullable String id, @Nullable Long seqNo, @Nullable Long primaryTerm,
|
||||||
@Nullable Long version) {
|
@Nullable Long version) {
|
||||||
this.id = id;
|
this.id = id;
|
||||||
this.seqNo = seqNo;
|
this.seqNo = seqNo;
|
||||||
@ -38,11 +38,12 @@ public class IndexedObjectInformation {
|
|||||||
this.version = version;
|
this.version = version;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static IndexedObjectInformation of(String id, @Nullable Long seqNo, @Nullable Long primaryTerm,
|
public static IndexedObjectInformation of(@Nullable String id, @Nullable Long seqNo, @Nullable Long primaryTerm,
|
||||||
@Nullable Long version) {
|
@Nullable Long version) {
|
||||||
return new IndexedObjectInformation(id, seqNo, primaryTerm, version);
|
return new IndexedObjectInformation(id, seqNo, primaryTerm, version);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Nullable
|
||||||
public String getId() {
|
public String getId() {
|
||||||
return id;
|
return id;
|
||||||
}
|
}
|
||||||
|
@ -275,27 +275,42 @@ public class ReactiveElasticsearchTemplate implements ReactiveElasticsearchOpera
|
|||||||
}
|
}
|
||||||
|
|
||||||
private <T> T updateIndexedObject(T entity, IndexedObjectInformation indexedObjectInformation) {
|
private <T> T updateIndexedObject(T entity, IndexedObjectInformation indexedObjectInformation) {
|
||||||
AdaptibleEntity<T> adaptibleEntity = operations.forEntity(entity, converter.getConversionService(),
|
|
||||||
routingResolver);
|
|
||||||
adaptibleEntity.populateIdIfNecessary(indexedObjectInformation.getId());
|
|
||||||
|
|
||||||
ElasticsearchPersistentEntity<?> persistentEntity = getPersistentEntityFor(entity.getClass());
|
ElasticsearchPersistentEntity<?> persistentEntity = converter.getMappingContext()
|
||||||
|
.getPersistentEntity(entity.getClass());
|
||||||
|
|
||||||
if (persistentEntity != null) {
|
if (persistentEntity != null) {
|
||||||
PersistentPropertyAccessor<Object> propertyAccessor = persistentEntity.getPropertyAccessor(entity);
|
PersistentPropertyAccessor<Object> propertyAccessor = persistentEntity.getPropertyAccessor(entity);
|
||||||
|
ElasticsearchPersistentProperty idProperty = persistentEntity.getIdProperty();
|
||||||
|
|
||||||
|
// Only deal with text because ES generated Ids are strings!
|
||||||
|
if (indexedObjectInformation.getId() != null && idProperty != null
|
||||||
|
&& idProperty.getType().isAssignableFrom(String.class)) {
|
||||||
|
propertyAccessor.setProperty(idProperty, indexedObjectInformation.getId());
|
||||||
|
}
|
||||||
|
|
||||||
if (indexedObjectInformation.getSeqNo() != null && indexedObjectInformation.getPrimaryTerm() != null
|
if (indexedObjectInformation.getSeqNo() != null && indexedObjectInformation.getPrimaryTerm() != null
|
||||||
&& persistentEntity.hasSeqNoPrimaryTermProperty()) {
|
&& persistentEntity.hasSeqNoPrimaryTermProperty()) {
|
||||||
ElasticsearchPersistentProperty seqNoPrimaryTermProperty = persistentEntity.getSeqNoPrimaryTermProperty();
|
ElasticsearchPersistentProperty seqNoPrimaryTermProperty = persistentEntity.getSeqNoPrimaryTermProperty();
|
||||||
|
// noinspection ConstantConditions
|
||||||
propertyAccessor.setProperty(seqNoPrimaryTermProperty,
|
propertyAccessor.setProperty(seqNoPrimaryTermProperty,
|
||||||
new SeqNoPrimaryTerm(indexedObjectInformation.getSeqNo(), indexedObjectInformation.getPrimaryTerm()));
|
new SeqNoPrimaryTerm(indexedObjectInformation.getSeqNo(), indexedObjectInformation.getPrimaryTerm()));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (indexedObjectInformation.getVersion() != null && persistentEntity.hasVersionProperty()) {
|
if (indexedObjectInformation.getVersion() != null && persistentEntity.hasVersionProperty()) {
|
||||||
ElasticsearchPersistentProperty versionProperty = persistentEntity.getVersionProperty();
|
ElasticsearchPersistentProperty versionProperty = persistentEntity.getVersionProperty();
|
||||||
|
// noinspection ConstantConditions
|
||||||
propertyAccessor.setProperty(versionProperty, indexedObjectInformation.getVersion());
|
propertyAccessor.setProperty(versionProperty, indexedObjectInformation.getVersion());
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
|
// noinspection unchecked
|
||||||
|
T updatedEntity = (T) propertyAccessor.getBean();
|
||||||
|
return updatedEntity;
|
||||||
|
} else {
|
||||||
|
AdaptibleEntity<T> adaptibleEntity = operations.forEntity(entity, converter.getConversionService(),
|
||||||
|
routingResolver);
|
||||||
|
adaptibleEntity.populateIdIfNecessary(indexedObjectInformation.getId());
|
||||||
|
}
|
||||||
return entity;
|
return entity;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -457,7 +472,7 @@ public class ReactiveElasticsearchTemplate implements ReactiveElasticsearchOpera
|
|||||||
|
|
||||||
DocumentCallback<T> callback = new ReadDocumentCallback<>(converter, entityType, index);
|
DocumentCallback<T> callback = new ReadDocumentCallback<>(converter, entityType, index);
|
||||||
|
|
||||||
return doGet(id, index).flatMap(it -> callback.toEntity(DocumentAdapters.from(it)));
|
return doGet(id, index).flatMap(response -> callback.toEntity(DocumentAdapters.from(response)));
|
||||||
}
|
}
|
||||||
|
|
||||||
private Mono<GetResult> doGet(String id, IndexCoordinates index) {
|
private Mono<GetResult> doGet(String id, IndexCoordinates index) {
|
||||||
@ -1097,6 +1112,10 @@ public class ReactiveElasticsearchTemplate implements ReactiveElasticsearchOpera
|
|||||||
}
|
}
|
||||||
|
|
||||||
T entity = reader.read(type, document);
|
T entity = reader.read(type, document);
|
||||||
|
IndexedObjectInformation indexedObjectInformation = IndexedObjectInformation.of(
|
||||||
|
document.hasId() ? document.getId() : null, document.getSeqNo(), document.getPrimaryTerm(),
|
||||||
|
document.getVersion());
|
||||||
|
entity = updateIndexedObject(entity, indexedObjectInformation);
|
||||||
return maybeCallAfterConvert(entity, document, index);
|
return maybeCallAfterConvert(entity, document, index);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -15,6 +15,7 @@
|
|||||||
*/
|
*/
|
||||||
package org.springframework.data.elasticsearch.core.join;
|
package org.springframework.data.elasticsearch.core.join;
|
||||||
|
|
||||||
|
import org.springframework.data.annotation.PersistenceConstructor;
|
||||||
import org.springframework.lang.Nullable;
|
import org.springframework.lang.Nullable;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -35,6 +36,7 @@ public class JoinField<ID> {
|
|||||||
this(name, null);
|
this(name, null);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@PersistenceConstructor
|
||||||
public JoinField(String name, @Nullable ID parent) {
|
public JoinField(String name, @Nullable ID parent) {
|
||||||
this.name = name;
|
this.name = name;
|
||||||
this.parent = parent;
|
this.parent = parent;
|
||||||
|
@ -35,7 +35,6 @@ import org.springframework.data.mapping.MappingException;
|
|||||||
import org.springframework.data.mapping.PropertyHandler;
|
import org.springframework.data.mapping.PropertyHandler;
|
||||||
import org.springframework.data.mapping.model.BasicPersistentEntity;
|
import org.springframework.data.mapping.model.BasicPersistentEntity;
|
||||||
import org.springframework.data.mapping.model.FieldNamingStrategy;
|
import org.springframework.data.mapping.model.FieldNamingStrategy;
|
||||||
import org.springframework.data.mapping.model.PersistentPropertyAccessorFactory;
|
|
||||||
import org.springframework.data.spel.ExpressionDependencies;
|
import org.springframework.data.spel.ExpressionDependencies;
|
||||||
import org.springframework.data.util.Lazy;
|
import org.springframework.data.util.Lazy;
|
||||||
import org.springframework.data.util.TypeInformation;
|
import org.springframework.data.util.TypeInformation;
|
||||||
@ -238,19 +237,6 @@ public class SimpleElasticsearchPersistentEntity<T> extends BasicPersistentEntit
|
|||||||
getType());
|
getType());
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
* (non-Javadoc)
|
|
||||||
* @see org.springframework.data.mapping.model.BasicPersistentEntity#setPersistentPropertyAccessorFactory(org.springframework.data.mapping.model.PersistentPropertyAccessorFactory)
|
|
||||||
*/
|
|
||||||
@SuppressWarnings("SpellCheckingInspection")
|
|
||||||
@Override
|
|
||||||
public void setPersistentPropertyAccessorFactory(PersistentPropertyAccessorFactory factory) {
|
|
||||||
|
|
||||||
// Do nothing to avoid the usage of ClassGeneratingPropertyAccessorFactory for now
|
|
||||||
// DATACMNS-1322 switches to proper immutability behavior which Spring Data Elasticsearch
|
|
||||||
// cannot yet implement
|
|
||||||
}
|
|
||||||
|
|
||||||
@Nullable
|
@Nullable
|
||||||
@Override
|
@Override
|
||||||
public ElasticsearchPersistentProperty getPersistentPropertyWithFieldName(String fieldName) {
|
public ElasticsearchPersistentProperty getPersistentPropertyWithFieldName(String fieldName) {
|
||||||
|
@ -279,11 +279,6 @@ public class SimpleElasticsearchPersistentProperty extends
|
|||||||
throw new UnsupportedOperationException();
|
throw new UnsupportedOperationException();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean isImmutable() {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean isSeqNoPrimaryTermProperty() {
|
public boolean isSeqNoPrimaryTermProperty() {
|
||||||
return isSeqNoPrimaryTerm;
|
return isSeqNoPrimaryTerm;
|
||||||
|
@ -60,7 +60,6 @@ import org.elasticsearch.search.fetch.subphase.highlight.HighlightBuilder;
|
|||||||
import org.elasticsearch.search.sort.FieldSortBuilder;
|
import org.elasticsearch.search.sort.FieldSortBuilder;
|
||||||
import org.elasticsearch.search.sort.SortBuilders;
|
import org.elasticsearch.search.sort.SortBuilders;
|
||||||
import org.elasticsearch.search.sort.SortOrder;
|
import org.elasticsearch.search.sort.SortOrder;
|
||||||
import org.junit.jupiter.api.AfterEach;
|
|
||||||
import org.junit.jupiter.api.BeforeEach;
|
import org.junit.jupiter.api.BeforeEach;
|
||||||
import org.junit.jupiter.api.DisplayName;
|
import org.junit.jupiter.api.DisplayName;
|
||||||
import org.junit.jupiter.api.Test;
|
import org.junit.jupiter.api.Test;
|
||||||
@ -137,7 +136,8 @@ public abstract class ElasticsearchTemplateTests {
|
|||||||
@BeforeEach
|
@BeforeEach
|
||||||
public void before() {
|
public void before() {
|
||||||
indexOperations = operations.indexOps(SampleEntity.class);
|
indexOperations = operations.indexOps(SampleEntity.class);
|
||||||
deleteIndices();
|
|
||||||
|
operations.indexOps(IndexCoordinates.of("*")).delete();
|
||||||
|
|
||||||
indexOperations.create();
|
indexOperations.create();
|
||||||
indexOperations.putMapping(SampleEntity.class);
|
indexOperations.putMapping(SampleEntity.class);
|
||||||
@ -155,29 +155,6 @@ public abstract class ElasticsearchTemplateTests {
|
|||||||
indexOpsJoinEntity.putMapping(SampleJoinEntity.class);
|
indexOpsJoinEntity.putMapping(SampleJoinEntity.class);
|
||||||
}
|
}
|
||||||
|
|
||||||
@AfterEach
|
|
||||||
public void after() {
|
|
||||||
|
|
||||||
deleteIndices();
|
|
||||||
}
|
|
||||||
|
|
||||||
private void deleteIndices() {
|
|
||||||
|
|
||||||
indexOperations.delete();
|
|
||||||
operations.indexOps(SampleEntityUUIDKeyed.class).delete();
|
|
||||||
operations.indexOps(UseServerConfigurationEntity.class).delete();
|
|
||||||
operations.indexOps(SampleMappingEntity.class).delete();
|
|
||||||
operations.indexOps(Book.class).delete();
|
|
||||||
operations.indexOps(IndexCoordinates.of(INDEX_1_NAME)).delete();
|
|
||||||
operations.indexOps(IndexCoordinates.of(INDEX_2_NAME)).delete();
|
|
||||||
operations.indexOps(IndexCoordinates.of(INDEX_3_NAME)).delete();
|
|
||||||
operations.indexOps(SearchHitsEntity.class).delete();
|
|
||||||
operations.indexOps(HighlightEntity.class).delete();
|
|
||||||
operations.indexOps(OptimisticEntity.class).delete();
|
|
||||||
operations.indexOps(OptimisticAndVersionedEntity.class).delete();
|
|
||||||
operations.indexOps(IndexCoordinates.of(INDEX_NAME_JOIN_SAMPLE_ENTITY)).delete();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test // DATAES-106
|
@Test // DATAES-106
|
||||||
public void shouldReturnCountForGivenCriteriaQuery() {
|
public void shouldReturnCountForGivenCriteriaQuery() {
|
||||||
|
|
||||||
@ -1126,7 +1103,8 @@ public abstract class ElasticsearchTemplateTests {
|
|||||||
Collection<String> ids = IntStream.rangeClosed(1, 10).mapToObj(i -> nextIdAsString()).collect(Collectors.toList());
|
Collection<String> ids = IntStream.rangeClosed(1, 10).mapToObj(i -> nextIdAsString()).collect(Collectors.toList());
|
||||||
ids.add(referenceId);
|
ids.add(referenceId);
|
||||||
ids.stream()
|
ids.stream()
|
||||||
.map(id -> getIndexQuery(SampleEntity.builder().id(id).message(sampleMessage).version(System.currentTimeMillis()).build()))
|
.map(id -> getIndexQuery(
|
||||||
|
SampleEntity.builder().id(id).message(sampleMessage).version(System.currentTimeMillis()).build()))
|
||||||
.forEach(indexQuery -> operations.index(indexQuery, index));
|
.forEach(indexQuery -> operations.index(indexQuery, index));
|
||||||
indexOperations.refresh();
|
indexOperations.refresh();
|
||||||
|
|
||||||
@ -1141,7 +1119,8 @@ public abstract class ElasticsearchTemplateTests {
|
|||||||
assertThat(searchHits.getTotalHits()).isEqualTo(10);
|
assertThat(searchHits.getTotalHits()).isEqualTo(10);
|
||||||
assertThat(searchHits.getSearchHits()).hasSize(5);
|
assertThat(searchHits.getSearchHits()).hasSize(5);
|
||||||
|
|
||||||
Collection<String> returnedIds = searchHits.getSearchHits().stream().map(SearchHit::getId).collect(Collectors.toList());
|
Collection<String> returnedIds = searchHits.getSearchHits().stream().map(SearchHit::getId)
|
||||||
|
.collect(Collectors.toList());
|
||||||
|
|
||||||
moreLikeThisQuery.setPageable(PageRequest.of(1, 5));
|
moreLikeThisQuery.setPageable(PageRequest.of(1, 5));
|
||||||
|
|
||||||
@ -3588,6 +3567,24 @@ public abstract class ElasticsearchTemplateTests {
|
|||||||
assertThat(explanation).isNotNull();
|
assertThat(explanation).isNotNull();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test // #1800
|
||||||
|
@DisplayName("should work with immutable classes")
|
||||||
|
void shouldWorkWithImmutableClasses() {
|
||||||
|
|
||||||
|
ImmutableEntity entity = new ImmutableEntity(null, "some text", null);
|
||||||
|
|
||||||
|
ImmutableEntity saved = operations.save(entity);
|
||||||
|
|
||||||
|
assertThat(saved).isNotNull();
|
||||||
|
assertThat(saved.getId()).isNotEmpty();
|
||||||
|
SeqNoPrimaryTerm seqNoPrimaryTerm = saved.getSeqNoPrimaryTerm();
|
||||||
|
assertThat(seqNoPrimaryTerm).isNotNull();
|
||||||
|
|
||||||
|
ImmutableEntity retrieved = operations.get(saved.getId(), ImmutableEntity.class);
|
||||||
|
|
||||||
|
assertThat(retrieved).isEqualTo(saved);
|
||||||
|
}
|
||||||
|
|
||||||
// region entities
|
// region entities
|
||||||
@Document(indexName = INDEX_NAME_SAMPLE_ENTITY)
|
@Document(indexName = INDEX_NAME_SAMPLE_ENTITY)
|
||||||
@Setting(shards = 1, replicas = 0, refreshInterval = "-1")
|
@Setting(shards = 1, replicas = 0, refreshInterval = "-1")
|
||||||
@ -4366,5 +4363,61 @@ public abstract class ElasticsearchTemplateTests {
|
|||||||
this.text = text;
|
this.text = text;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
//endregion
|
|
||||||
|
@Document(indexName = "immutable-class")
|
||||||
|
private static final class ImmutableEntity {
|
||||||
|
@Id private final String id;
|
||||||
|
@Field(type = FieldType.Text) private final String text;
|
||||||
|
@Nullable private final SeqNoPrimaryTerm seqNoPrimaryTerm;
|
||||||
|
|
||||||
|
public ImmutableEntity(@Nullable String id, String text, @Nullable SeqNoPrimaryTerm seqNoPrimaryTerm) {
|
||||||
|
this.id = id;
|
||||||
|
this.text = text;
|
||||||
|
this.seqNoPrimaryTerm = seqNoPrimaryTerm;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getId() {
|
||||||
|
return id;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getText() {
|
||||||
|
return text;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Nullable
|
||||||
|
public SeqNoPrimaryTerm getSeqNoPrimaryTerm() {
|
||||||
|
return seqNoPrimaryTerm;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean equals(Object o) {
|
||||||
|
if (this == o)
|
||||||
|
return true;
|
||||||
|
if (o == null || getClass() != o.getClass())
|
||||||
|
return false;
|
||||||
|
|
||||||
|
ImmutableEntity that = (ImmutableEntity) o;
|
||||||
|
|
||||||
|
if (!id.equals(that.id))
|
||||||
|
return false;
|
||||||
|
if (!text.equals(that.text))
|
||||||
|
return false;
|
||||||
|
return seqNoPrimaryTerm != null ? seqNoPrimaryTerm.equals(that.seqNoPrimaryTerm) : that.seqNoPrimaryTerm == null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int hashCode() {
|
||||||
|
int result = id.hashCode();
|
||||||
|
result = 31 * result + text.hashCode();
|
||||||
|
result = 31 * result + (seqNoPrimaryTerm != null ? seqNoPrimaryTerm.hashCode() : 0);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
return "ImmutableEntity{" + "id='" + id + '\'' + ", text='" + text + '\'' + ", seqNoPrimaryTerm="
|
||||||
|
+ seqNoPrimaryTerm + '}';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// endregion
|
||||||
}
|
}
|
||||||
|
@ -36,6 +36,7 @@ import java.util.LinkedHashMap;
|
|||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.UUID;
|
import java.util.UUID;
|
||||||
|
import java.util.concurrent.atomic.AtomicReference;
|
||||||
import java.util.stream.Collectors;
|
import java.util.stream.Collectors;
|
||||||
import java.util.stream.IntStream;
|
import java.util.stream.IntStream;
|
||||||
|
|
||||||
@ -64,6 +65,7 @@ import org.springframework.data.domain.Sort;
|
|||||||
import org.springframework.data.elasticsearch.UncategorizedElasticsearchException;
|
import org.springframework.data.elasticsearch.UncategorizedElasticsearchException;
|
||||||
import org.springframework.data.elasticsearch.annotations.Document;
|
import org.springframework.data.elasticsearch.annotations.Document;
|
||||||
import org.springframework.data.elasticsearch.annotations.Field;
|
import org.springframework.data.elasticsearch.annotations.Field;
|
||||||
|
import org.springframework.data.elasticsearch.annotations.FieldType;
|
||||||
import org.springframework.data.elasticsearch.annotations.Mapping;
|
import org.springframework.data.elasticsearch.annotations.Mapping;
|
||||||
import org.springframework.data.elasticsearch.annotations.Setting;
|
import org.springframework.data.elasticsearch.annotations.Setting;
|
||||||
import org.springframework.data.elasticsearch.client.reactive.ReactiveElasticsearchClient;
|
import org.springframework.data.elasticsearch.client.reactive.ReactiveElasticsearchClient;
|
||||||
@ -1149,6 +1151,26 @@ public class ReactiveElasticsearchTemplateIntegrationTests {
|
|||||||
}).verifyComplete();
|
}).verifyComplete();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test // #1800
|
||||||
|
@DisplayName("should work with immutable classes")
|
||||||
|
void shouldWorkWithImmutableClasses() {
|
||||||
|
|
||||||
|
ImmutableEntity entity = new ImmutableEntity(null, "some text", null);
|
||||||
|
AtomicReference<ImmutableEntity> savedEntity = new AtomicReference<>();
|
||||||
|
|
||||||
|
template.save(entity).as(StepVerifier::create).consumeNextWith(saved -> {
|
||||||
|
assertThat(saved).isNotNull();
|
||||||
|
savedEntity.set(saved);
|
||||||
|
assertThat(saved.getId()).isNotEmpty();
|
||||||
|
SeqNoPrimaryTerm seqNoPrimaryTerm = saved.getSeqNoPrimaryTerm();
|
||||||
|
assertThat(seqNoPrimaryTerm).isNotNull();
|
||||||
|
}).verifyComplete();
|
||||||
|
|
||||||
|
template.get(savedEntity.get().getId(), ImmutableEntity.class).as(StepVerifier::create)
|
||||||
|
.consumeNextWith(retrieved -> {
|
||||||
|
assertThat(retrieved).isEqualTo(savedEntity.get());
|
||||||
|
}).verifyComplete();
|
||||||
|
}
|
||||||
// endregion
|
// endregion
|
||||||
|
|
||||||
// region Helper functions
|
// region Helper functions
|
||||||
@ -1243,8 +1265,10 @@ public class ReactiveElasticsearchTemplateIntegrationTests {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean equals(Object o) {
|
public boolean equals(Object o) {
|
||||||
if (this == o) return true;
|
if (this == o)
|
||||||
if (o == null || getClass() != o.getClass()) return false;
|
return true;
|
||||||
|
if (o == null || getClass() != o.getClass())
|
||||||
|
return false;
|
||||||
|
|
||||||
Message message1 = (Message) o;
|
Message message1 = (Message) o;
|
||||||
|
|
||||||
@ -1301,14 +1325,19 @@ public class ReactiveElasticsearchTemplateIntegrationTests {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean equals(Object o) {
|
public boolean equals(Object o) {
|
||||||
if (this == o) return true;
|
if (this == o)
|
||||||
if (o == null || getClass() != o.getClass()) return false;
|
return true;
|
||||||
|
if (o == null || getClass() != o.getClass())
|
||||||
|
return false;
|
||||||
|
|
||||||
SampleEntity that = (SampleEntity) o;
|
SampleEntity that = (SampleEntity) o;
|
||||||
|
|
||||||
if (rate != that.rate) return false;
|
if (rate != that.rate)
|
||||||
if (id != null ? !id.equals(that.id) : that.id != null) return false;
|
return false;
|
||||||
if (message != null ? !message.equals(that.message) : that.message != null) return false;
|
if (id != null ? !id.equals(that.id) : that.id != null)
|
||||||
|
return false;
|
||||||
|
if (message != null ? !message.equals(that.message) : that.message != null)
|
||||||
|
return false;
|
||||||
return version != null ? version.equals(that.version) : that.version == null;
|
return version != null ? version.equals(that.version) : that.version == null;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1440,5 +1469,60 @@ public class ReactiveElasticsearchTemplateIntegrationTests {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Document(indexName = "immutable-class")
|
||||||
|
private static final class ImmutableEntity {
|
||||||
|
@Id private final String id;
|
||||||
|
@Field(type = FieldType.Text) private final String text;
|
||||||
|
@Nullable private final SeqNoPrimaryTerm seqNoPrimaryTerm;
|
||||||
|
|
||||||
|
public ImmutableEntity(@Nullable String id, String text, @Nullable SeqNoPrimaryTerm seqNoPrimaryTerm) {
|
||||||
|
this.id = id;
|
||||||
|
this.text = text;
|
||||||
|
this.seqNoPrimaryTerm = seqNoPrimaryTerm;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getId() {
|
||||||
|
return id;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getText() {
|
||||||
|
return text;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Nullable
|
||||||
|
public SeqNoPrimaryTerm getSeqNoPrimaryTerm() {
|
||||||
|
return seqNoPrimaryTerm;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean equals(Object o) {
|
||||||
|
if (this == o)
|
||||||
|
return true;
|
||||||
|
if (o == null || getClass() != o.getClass())
|
||||||
|
return false;
|
||||||
|
|
||||||
|
ImmutableEntity that = (ImmutableEntity) o;
|
||||||
|
|
||||||
|
if (!id.equals(that.id))
|
||||||
|
return false;
|
||||||
|
if (!text.equals(that.text))
|
||||||
|
return false;
|
||||||
|
return seqNoPrimaryTerm != null ? seqNoPrimaryTerm.equals(that.seqNoPrimaryTerm) : that.seqNoPrimaryTerm == null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int hashCode() {
|
||||||
|
int result = id.hashCode();
|
||||||
|
result = 31 * result + text.hashCode();
|
||||||
|
result = 31 * result + (seqNoPrimaryTerm != null ? seqNoPrimaryTerm.hashCode() : 0);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
return "ImmutableEntity{" + "id='" + id + '\'' + ", text='" + text + '\'' + ", seqNoPrimaryTerm="
|
||||||
|
+ seqNoPrimaryTerm + '}';
|
||||||
|
}
|
||||||
|
}
|
||||||
// endregion
|
// endregion
|
||||||
}
|
}
|
||||||
|
@ -25,6 +25,7 @@ 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.context.annotation.Import;
|
import org.springframework.context.annotation.Import;
|
||||||
|
import org.springframework.data.annotation.PersistenceConstructor;
|
||||||
import org.springframework.data.elasticsearch.annotations.Document;
|
import org.springframework.data.elasticsearch.annotations.Document;
|
||||||
import org.springframework.data.elasticsearch.core.ElasticsearchOperations;
|
import org.springframework.data.elasticsearch.core.ElasticsearchOperations;
|
||||||
import org.springframework.data.elasticsearch.core.IndexOperations;
|
import org.springframework.data.elasticsearch.core.IndexOperations;
|
||||||
@ -95,11 +96,16 @@ public class ImmutableElasticsearchRepositoryTests {
|
|||||||
static class ImmutableEntity {
|
static class ImmutableEntity {
|
||||||
private final String id, name;
|
private final String id, name;
|
||||||
|
|
||||||
public ImmutableEntity(String name) {
|
@PersistenceConstructor
|
||||||
this.id = null;
|
public ImmutableEntity(String id, String name) {
|
||||||
|
this.id = id;
|
||||||
this.name = name;
|
this.name = name;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public ImmutableEntity(String name) {
|
||||||
|
this(null, name);
|
||||||
|
}
|
||||||
|
|
||||||
public String getId() {
|
public String getId() {
|
||||||
return id;
|
return id;
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user