Many resources are needed to download a project. Please understand that we have to compensate our server costs. Thank you in advance. Project price only 1 $
You can buy this project and download/modify it how often you want.
/*
* Copyright 2015-2020 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.redis.core;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicReference;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.context.ApplicationEventPublisher;
import org.springframework.context.ApplicationListener;
import org.springframework.core.convert.ConversionService;
import org.springframework.core.convert.ConverterNotFoundException;
import org.springframework.data.keyvalue.core.AbstractKeyValueAdapter;
import org.springframework.data.keyvalue.core.KeyValueAdapter;
import org.springframework.data.mapping.PersistentPropertyAccessor;
import org.springframework.data.redis.connection.DataType;
import org.springframework.data.redis.connection.Message;
import org.springframework.data.redis.connection.MessageListener;
import org.springframework.data.redis.connection.RedisConnection;
import org.springframework.data.redis.core.PartialUpdate.PropertyUpdate;
import org.springframework.data.redis.core.PartialUpdate.UpdateCommand;
import org.springframework.data.redis.core.RedisKeyValueAdapter.RedisUpdateObject.Index;
import org.springframework.data.redis.core.convert.CustomConversions;
import org.springframework.data.redis.core.convert.GeoIndexedPropertyValue;
import org.springframework.data.redis.core.convert.KeyspaceConfiguration;
import org.springframework.data.redis.core.convert.MappingRedisConverter;
import org.springframework.data.redis.core.convert.MappingRedisConverter.BinaryKeyspaceIdentifier;
import org.springframework.data.redis.core.convert.MappingRedisConverter.KeyspaceIdentifier;
import org.springframework.data.redis.core.convert.PathIndexResolver;
import org.springframework.data.redis.core.convert.RedisConverter;
import org.springframework.data.redis.core.convert.RedisCustomConversions;
import org.springframework.data.redis.core.convert.RedisData;
import org.springframework.data.redis.core.convert.ReferenceResolverImpl;
import org.springframework.data.redis.core.mapping.RedisMappingContext;
import org.springframework.data.redis.core.mapping.RedisPersistentEntity;
import org.springframework.data.redis.core.mapping.RedisPersistentProperty;
import org.springframework.data.redis.listener.KeyExpirationEventMessageListener;
import org.springframework.data.redis.listener.RedisMessageListenerContainer;
import org.springframework.data.redis.util.ByteUtils;
import org.springframework.data.util.CloseableIterator;
import org.springframework.lang.Nullable;
import org.springframework.util.Assert;
import org.springframework.util.CollectionUtils;
import org.springframework.util.ObjectUtils;
/**
* Redis specific {@link KeyValueAdapter} implementation. Uses binary codec to read/write data from/to Redis. Objects
* are stored in a Redis Hash using the value of {@link RedisHash}, the {@link KeyspaceConfiguration} or just
* {@link Class#getName()} as a prefix.
* Example
*
*
*
* @RedisHash("persons")
* class Person {
* @Id String id;
* String name;
* }
*
*
* prefix ID
* | |
* V V
* hgetall persons:5d67b7e1-8640-4475-beeb-c666fab4c0e5
* 1) id
* 2) 5d67b7e1-8640-4475-beeb-c666fab4c0e5
* 3) name
* 4) Rand al'Thor
*
*
*
*
* The {@link KeyValueAdapter} is not intended to store simple types such as {@link String} values.
* Please use {@link RedisTemplate} for this purpose.
*
* @author Christoph Strobl
* @author Mark Paluch
* @since 1.7
*/
public class RedisKeyValueAdapter extends AbstractKeyValueAdapter
implements InitializingBean, ApplicationContextAware, ApplicationListener {
/**
* Time To Live in seconds that phantom keys should live longer than the actual key.
*/
private static final int PHANTOM_KEY_TTL = 300;
private RedisOperations redisOps;
private RedisConverter converter;
private @Nullable RedisMessageListenerContainer messageListenerContainer;
private final AtomicReference expirationListener = new AtomicReference<>(null);
private @Nullable ApplicationEventPublisher eventPublisher;
private EnableKeyspaceEvents enableKeyspaceEvents = EnableKeyspaceEvents.OFF;
private @Nullable String keyspaceNotificationsConfigParameter = null;
private ShadowCopy shadowCopy = ShadowCopy.DEFAULT;
/**
* Creates new {@link RedisKeyValueAdapter} with default {@link RedisMappingContext} and default
* {@link RedisCustomConversions}.
*
* @param redisOps must not be {@literal null}.
*/
public RedisKeyValueAdapter(RedisOperations redisOps) {
this(redisOps, new RedisMappingContext());
}
/**
* Creates new {@link RedisKeyValueAdapter} with default {@link RedisCustomConversions}.
*
* @param redisOps must not be {@literal null}.
* @param mappingContext must not be {@literal null}.
*/
public RedisKeyValueAdapter(RedisOperations redisOps, RedisMappingContext mappingContext) {
this(redisOps, mappingContext, new RedisCustomConversions());
}
/**
* Creates new {@link RedisKeyValueAdapter}.
*
* @param redisOps must not be {@literal null}.
* @param mappingContext must not be {@literal null}.
* @param customConversions can be {@literal null}.
* @deprecated since 2.0, use
* {@link #RedisKeyValueAdapter(RedisOperations, RedisMappingContext, org.springframework.data.convert.CustomConversions)}.
*/
@Deprecated
public RedisKeyValueAdapter(RedisOperations redisOps, RedisMappingContext mappingContext,
CustomConversions customConversions) {
this(redisOps, mappingContext, (org.springframework.data.convert.CustomConversions) customConversions);
}
/**
* Creates new {@link RedisKeyValueAdapter}.
*
* @param redisOps must not be {@literal null}.
* @param mappingContext must not be {@literal null}.
* @param customConversions can be {@literal null}.
* @since 2.0
*/
public RedisKeyValueAdapter(RedisOperations redisOps, RedisMappingContext mappingContext,
@Nullable org.springframework.data.convert.CustomConversions customConversions) {
super(new RedisQueryEngine());
Assert.notNull(redisOps, "RedisOperations must not be null!");
Assert.notNull(mappingContext, "RedisMappingContext must not be null!");
MappingRedisConverter mappingConverter = new MappingRedisConverter(mappingContext,
new PathIndexResolver(mappingContext), new ReferenceResolverImpl(redisOps));
mappingConverter.setCustomConversions(customConversions == null ? new RedisCustomConversions() : customConversions);
mappingConverter.afterPropertiesSet();
this.converter = mappingConverter;
this.redisOps = redisOps;
initMessageListenerContainer();
}
/**
* Creates new {@link RedisKeyValueAdapter} with specific {@link RedisConverter}.
*
* @param redisOps must not be {@literal null}.
* @param redisConverter must not be {@literal null}.
*/
public RedisKeyValueAdapter(RedisOperations redisOps, RedisConverter redisConverter) {
super(new RedisQueryEngine());
Assert.notNull(redisOps, "RedisOperations must not be null!");
this.converter = redisConverter;
this.redisOps = redisOps;
initMessageListenerContainer();
}
/**
* Default constructor.
*/
protected RedisKeyValueAdapter() {}
/*
* (non-Javadoc)
* @see org.springframework.data.keyvalue.core.KeyValueAdapter#put(java.lang.Object, java.lang.Object, java.lang.String)
*/
@Override
public Object put(Object id, Object item, String keyspace) {
RedisData rdo = item instanceof RedisData ? (RedisData) item : new RedisData();
if (!(item instanceof RedisData)) {
converter.write(item, rdo);
}
if (ObjectUtils.nullSafeEquals(EnableKeyspaceEvents.ON_DEMAND, enableKeyspaceEvents)
&& this.expirationListener.get() == null) {
if (rdo.getTimeToLive() != null && rdo.getTimeToLive() > 0) {
initKeyExpirationListener();
}
}
if (rdo.getId() == null) {
rdo.setId(converter.getConversionService().convert(id, String.class));
}
redisOps.execute((RedisCallback