spring-data-elasticsearch EntityOperations 源码
spring-data-elasticsearch EntityOperations 代码
文件路径:/src/main/java/org/springframework/data/elasticsearch/core/EntityOperations.java
/*
* Copyright 2018-2022 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.data.elasticsearch.core;
import java.util.Map;
import org.springframework.core.convert.ConversionService;
import org.springframework.data.elasticsearch.core.join.JoinField;
import org.springframework.data.elasticsearch.core.mapping.ElasticsearchPersistentEntity;
import org.springframework.data.elasticsearch.core.mapping.ElasticsearchPersistentProperty;
import org.springframework.data.elasticsearch.core.mapping.IndexCoordinates;
import org.springframework.data.elasticsearch.core.query.SeqNoPrimaryTerm;
import org.springframework.data.elasticsearch.core.routing.RoutingResolver;
import org.springframework.data.mapping.IdentifierAccessor;
import org.springframework.data.mapping.PersistentPropertyAccessor;
import org.springframework.data.mapping.context.MappingContext;
import org.springframework.data.mapping.model.ConvertingPropertyAccessor;
import org.springframework.lang.Nullable;
import org.springframework.util.Assert;
/**
* Common operations performed on an entity in the context of it's mapping metadata.
*
* @author Mark Paluch
* @author Christoph Strobl
* @author Peter-Josef Meisch
* @author Roman Puchkovskiy
* @since 3.2
*/
public class EntityOperations {
private static final String ID_FIELD = "id";
private final MappingContext<? extends ElasticsearchPersistentEntity<?>, ElasticsearchPersistentProperty> context;
public EntityOperations(
MappingContext<? extends ElasticsearchPersistentEntity<?>, ElasticsearchPersistentProperty> context) {
Assert.notNull(context, "context must not be null");
this.context = context;
}
/**
* Creates a new {@link Entity} for the given bean.
*
* @param entity must not be {@literal null}.
* @return
*/
@SuppressWarnings({ "unchecked", "rawtypes" })
<T> Entity<T> forEntity(T entity) {
Assert.notNull(entity, "Bean must not be null!");
if (entity instanceof Map) {
return new SimpleMappedEntity((Map<String, Object>) entity);
}
return MappedEntity.of(entity, context);
}
/**
* Creates a new {@link AdaptableEntity} for the given bean and {@link ConversionService} and {@link RoutingResolver}.
*
* @param entity must not be {@literal null}.
* @param conversionService must not be {@literal null}.
* @param routingResolver the {@link RoutingResolver}, must not be {@literal null}
* @return the {@link AdaptableEntity}
*/
@SuppressWarnings({ "unchecked", "rawtypes" })
public <T> AdaptableEntity<T> forEntity(T entity, ConversionService conversionService,
RoutingResolver routingResolver) {
Assert.notNull(entity, "Bean must not be null!");
Assert.notNull(conversionService, "ConversionService must not be null!");
if (entity instanceof Map) {
return new SimpleMappedEntity((Map<String, Object>) entity);
}
return AdaptableMappedEntity.of(entity, context, conversionService, routingResolver);
}
/**
* Determine index name and type name from {@link Entity} with {@code index} and {@code type} overrides. Allows using
* preferred values for index and type if provided, otherwise fall back to index and type defined on entity level.
*
* @param entity the entity to determine the index name. Can be {@literal null} if {@code index} and {@literal type}
* are provided.
* @param index index name override can be {@literal null}.
* @return the {@link IndexCoordinates} containing index name and index type.
*/
IndexCoordinates determineIndex(Entity<?> entity, @Nullable String index) {
return determineIndex(entity.getPersistentEntity(), index);
}
/**
* Determine index name and type name from {@link ElasticsearchPersistentEntity} with {@code index} and {@code type}
* overrides. Allows using preferred values for index and type if provided, otherwise fall back to index and type
* defined on entity level.
*
* @param persistentEntity the entity to determine the index name. Can be {@literal null} if {@code index} and
* {@literal type} are provided.
* @param index index name override can be {@literal null}.
* @return the {@link IndexCoordinates} containing index name and index type.
* @since 4.1
*/
IndexCoordinates determineIndex(ElasticsearchPersistentEntity<?> persistentEntity, @Nullable String index) {
return index != null ? IndexCoordinates.of(index) : persistentEntity.getIndexCoordinates();
}
/**
* A representation of information about an entity.
*
* @author Christoph Strobl
*/
interface Entity<T> {
/**
* Returns the identifier of the entity.
*
* @return the ID value, can be {@literal null}.
*/
@Nullable
Object getId();
/**
* Returns whether the entity is versioned, i.e. if it contains a version property.
*
* @return
*/
default boolean isVersionedEntity() {
return false;
}
/**
* Returns the value of the version if the entity has a version property, {@literal null} otherwise.
*
* @return
*/
@Nullable
Object getVersion();
/**
* Returns the underlying bean.
*
* @return
*/
T getBean();
/**
* Returns whether the entity is considered to be new.
*
* @return
*/
boolean isNew();
/**
* Returns the {@link ElasticsearchPersistentEntity} associated with this entity.
*
* @return can be {@literal null} if this entity is not mapped.
*/
@Nullable
ElasticsearchPersistentEntity<?> getPersistentEntity();
/**
* Returns the required {@link ElasticsearchPersistentEntity}.
*
* @return
* @throws IllegalStateException if no {@link ElasticsearchPersistentEntity} is associated with this entity.
*/
default ElasticsearchPersistentEntity<?> getRequiredPersistentEntity() {
ElasticsearchPersistentEntity<?> persistentEntity = getPersistentEntity();
if (persistentEntity == null) {
throw new IllegalStateException("No ElasticsearchPersistentEntity available for this entity!");
}
return persistentEntity;
}
}
/**
* Information and commands on an entity.
*
* @author Mark Paluch
* @author Christoph Strobl
*/
public interface AdaptableEntity<T> extends Entity<T> {
/**
* Populates the identifier of the backing entity if it has an identifier property and there's no identifier
* currently present.
*
* @param id can be {@literal null}.
* @return can be {@literal null}.
*/
@Nullable
T populateIdIfNecessary(@Nullable Object id);
/**
* Initializes the version property of the of the current entity if available.
*
* @return the entity with the version property updated if available.
*/
T initializeVersionProperty();
/**
* Increments the value of the version property if available.
*
* @return the entity with the version property incremented if available.
*/
T incrementVersion();
/**
* Returns the current version value if the entity has a version property.
*
* @return the current version or {@literal null} in case it's uninitialized or the entity doesn't expose a version
* property.
*/
@Override
@Nullable
Number getVersion();
/**
* Returns whether there is a property with type SeqNoPrimaryTerm in this entity.
*
* @return true if there is SeqNoPrimaryTerm property
* @since 4.0
*/
boolean hasSeqNoPrimaryTerm();
/**
* Returns SeqNoPropertyTerm for this entity.
*
* @return SeqNoPrimaryTerm, may be {@literal null}
* @since 4.0
*/
@Nullable
SeqNoPrimaryTerm getSeqNoPrimaryTerm();
/**
* returns the routing for the entity if it is available
*
* @return routing if available
* @since 4.1
*/
@Nullable
String getRouting();
}
/**
* @param <T>
* @author Christoph Strobl
* @since 3.2
*/
private static class MapBackedEntity<T extends Map<String, Object>> implements AdaptableEntity<T> {
public MapBackedEntity(T map) {
Assert.notNull(map, "map must not be null");
this.map = map;
}
private final T map;
/*
* (non-Javadoc)
* @see org.springframework.data.elasticsearch.core.EntityOperations.Entity#getId()
*/
@Override
public Object getId() {
return map.get(ID_FIELD);
}
/*
* (non-Javadoc)
* @see org.springframework.data.elasticsearch.core.EntityOperations.AdaptableEntity#populateIdIfNecessary(java.lang.Object)
*/
@Nullable
@Override
public T populateIdIfNecessary(@Nullable Object id) {
map.put(ID_FIELD, id);
return map;
}
/*
* (non-Javadoc)
* @see org.springframework.data.elasticsearch.core.EntityOperations.AdaptableEntity#initializeVersionProperty()
*/
@Override
public T initializeVersionProperty() {
return map;
}
/*
* (non-Javadoc)
* @see org.springframework.data.elasticsearch.core.EntityOperations.AdaptableEntity#getVersion()
*/
@Override
@Nullable
public Number getVersion() {
return null;
}
@Override
public boolean hasSeqNoPrimaryTerm() {
return false;
}
@Override
public SeqNoPrimaryTerm getSeqNoPrimaryTerm() {
return null;
}
/*
* (non-Javadoc)
* @see org.springframework.data.elasticsearch.core.EntityOperations.AdaptableEntity#incrementVersion()
*/
@Override
public T incrementVersion() {
return map;
}
/*
* (non-Javadoc)
* @see org.springframework.data.elasticsearch.core.EntityOperations.Entity#getBean()
*/
@Override
public T getBean() {
return map;
}
/*
* (non-Javadoc)
* @see org.springframework.data.elasticsearch.core.EntityOperations.Entity#isNew()
*/
@Override
public boolean isNew() {
return map.get(ID_FIELD) != null;
}
/*
* (non-Javadoc)
* @see org.springframework.data.elasticsearch.core.EntityOperations.Entity#getPersistentEntity()
*/
@Override
public ElasticsearchPersistentEntity<?> getPersistentEntity() {
return null;
}
@Override
public String getRouting() {
return null;
}
}
/**
* Plain entity without applying further mapping.
*
* @param <T>
* @since 3.2
*/
private static class UnmappedEntity<T extends Map<String, Object>> extends MapBackedEntity<T> {
UnmappedEntity(T map) {
super(map);
}
}
/**
* Simple mapped entity without an associated {@link ElasticsearchPersistentEntity}.
*
* @param <T>
* @since 3.2
*/
private static class SimpleMappedEntity<T extends Map<String, Object>> extends MapBackedEntity<T> {
SimpleMappedEntity(T map) {
super(map);
}
/*
* (non-Javadoc)
* @see org.springframework.data.elasticsearch.core.EntityOperations.UnmappedEntity#getId()
*/
@Override
public Object getId() {
return getBean().get(ID_FIELD);
}
}
/**
* Mapped entity with an associated {@link ElasticsearchPersistentEntity}.
*
* @param <T>
* @since 3.2
*/
private static class MappedEntity<T> implements Entity<T> {
private final ElasticsearchPersistentEntity<?> entity;
private final IdentifierAccessor idAccessor;
private final PersistentPropertyAccessor<T> propertyAccessor;
private MappedEntity(ElasticsearchPersistentEntity<?> entity, IdentifierAccessor idAccessor,
PersistentPropertyAccessor<T> propertyAccessor) {
Assert.notNull(entity, "entity must not ne null");
Assert.notNull(idAccessor, "idAccessor must not ne null");
Assert.notNull(propertyAccessor, "propertyAccessor must not ne null");
this.entity = entity;
this.idAccessor = idAccessor;
this.propertyAccessor = propertyAccessor;
}
private static <T> MappedEntity<T> of(T bean,
MappingContext<? extends ElasticsearchPersistentEntity<?>, ElasticsearchPersistentProperty> context) {
ElasticsearchPersistentEntity<?> entity = context.getRequiredPersistentEntity(bean.getClass());
IdentifierAccessor identifierAccessor = entity.getIdentifierAccessor(bean);
PersistentPropertyAccessor<T> propertyAccessor = entity.getPropertyAccessor(bean);
return new MappedEntity<>(entity, identifierAccessor, propertyAccessor);
}
@Override
public Object getId() {
return idAccessor.getIdentifier();
}
@Override
public boolean isVersionedEntity() {
return entity.hasVersionProperty();
}
@Override
@Nullable
public Object getVersion() {
return propertyAccessor.getProperty(entity.getVersionProperty());
}
@Override
public T getBean() {
return propertyAccessor.getBean();
}
@Override
public boolean isNew() {
return entity.isNew(propertyAccessor.getBean());
}
@Override
public ElasticsearchPersistentEntity<?> getPersistentEntity() {
return entity;
}
}
/**
* @param <T>
* @since 3.2
*/
private static class AdaptableMappedEntity<T> extends MappedEntity<T> implements AdaptableEntity<T> {
private final ElasticsearchPersistentEntity<?> entity;
private final ConvertingPropertyAccessor<T> propertyAccessor;
private final IdentifierAccessor identifierAccessor;
private final ConversionService conversionService;
private final RoutingResolver routingResolver;
private AdaptableMappedEntity(T bean, ElasticsearchPersistentEntity<?> entity,
IdentifierAccessor identifierAccessor, ConvertingPropertyAccessor<T> propertyAccessor,
ConversionService conversionService, RoutingResolver routingResolver) {
super(entity, identifierAccessor, propertyAccessor);
this.entity = entity;
this.propertyAccessor = propertyAccessor;
this.identifierAccessor = identifierAccessor;
this.conversionService = conversionService;
this.routingResolver = routingResolver;
}
static <T> AdaptableEntity<T> of(T bean,
MappingContext<? extends ElasticsearchPersistentEntity<?>, ElasticsearchPersistentProperty> context,
ConversionService conversionService, RoutingResolver routingResolver) {
ElasticsearchPersistentEntity<?> entity = context.getRequiredPersistentEntity(bean.getClass());
IdentifierAccessor identifierAccessor = entity.getIdentifierAccessor(bean);
PersistentPropertyAccessor<T> propertyAccessor = entity.getPropertyAccessor(bean);
return new AdaptableMappedEntity<>(bean, entity, identifierAccessor,
new ConvertingPropertyAccessor<>(propertyAccessor, conversionService), conversionService, routingResolver);
}
@Override
public T getBean() {
return propertyAccessor.getBean();
}
@Nullable
@Override
public T populateIdIfNecessary(@Nullable Object id) {
if (id == null) {
return null;
}
T bean = propertyAccessor.getBean();
ElasticsearchPersistentProperty idProperty = entity.getIdProperty();
if (idProperty == null) {
return bean;
}
if (identifierAccessor.getIdentifier() != null) {
return bean;
}
propertyAccessor.setProperty(idProperty, id);
return propertyAccessor.getBean();
}
@Override
@Nullable
public Number getVersion() {
ElasticsearchPersistentProperty versionProperty = entity.getVersionProperty();
return versionProperty != null ? propertyAccessor.getProperty(versionProperty, Number.class) : null;
}
@Override
public boolean hasSeqNoPrimaryTerm() {
return entity.hasSeqNoPrimaryTermProperty();
}
@Override
public SeqNoPrimaryTerm getSeqNoPrimaryTerm() {
ElasticsearchPersistentProperty seqNoPrimaryTermProperty = entity.getRequiredSeqNoPrimaryTermProperty();
return propertyAccessor.getProperty(seqNoPrimaryTermProperty, SeqNoPrimaryTerm.class);
}
@Override
public T initializeVersionProperty() {
if (!entity.hasVersionProperty()) {
return propertyAccessor.getBean();
}
ElasticsearchPersistentProperty versionProperty = entity.getRequiredVersionProperty();
propertyAccessor.setProperty(versionProperty, versionProperty.getType().isPrimitive() ? 1 : 0);
return propertyAccessor.getBean();
}
@Override
public T incrementVersion() {
ElasticsearchPersistentProperty versionProperty = entity.getRequiredVersionProperty();
Number version = getVersion();
Number nextVersion = version == null ? 0 : version.longValue() + 1;
propertyAccessor.setProperty(versionProperty, nextVersion);
return propertyAccessor.getBean();
}
@Override
public String getRouting() {
String routing = routingResolver.getRouting(propertyAccessor.getBean());
if (routing != null) {
return routing;
}
ElasticsearchPersistentProperty joinFieldProperty = entity.getJoinFieldProperty();
if (joinFieldProperty != null) {
JoinField<?> joinField = propertyAccessor.getProperty(joinFieldProperty, JoinField.class);
if (joinField != null && joinField.getParent() != null) {
return conversionService.convert(joinField.getParent(), String.class);
}
}
return null;
}
}
}
相关信息
spring-data-elasticsearch 源码目录
相关文章
spring-data-elasticsearch AbstractElasticsearchTemplate 源码
spring-data-elasticsearch AbstractIndexTemplate 源码
spring-data-elasticsearch AbstractReactiveElasticsearchTemplate 源码
spring-data-elasticsearch ActiveShardCount 源码
spring-data-elasticsearch AggregationContainer 源码
spring-data-elasticsearch AggregationsContainer 源码
spring-data-elasticsearch DocumentOperations 源码
spring-data-elasticsearch ElasticsearchOperations 源码
0
赞
热门推荐
-
2、 - 优质文章
-
3、 gate.io
-
8、 golang
-
9、 openharmony
-
10、 Vue中input框自动聚焦