使用Spring Data Redis时抛出NoSuchElementException: No value present如何解决
异常原因
java.util.NoSuchElementException: No value present 异常的直接触发逻辑是CrudRepository.findById()方法返回Optional类型容器,当容器内不存在查询结果时直接调用get()方法就会抛出该异常。你的场景中具体触发原因包含以下几点:
- 查询ID不存在:测试代码直接使用
UUID.randomUUID().toString()作为查询ID,随机生成的ID默认在Redis中没有对应缓存数据,必然返回空的Optional容器。 - Repository泛型配置错误:你定义的Repository继承
CrudRepository<repoRedisEntity, String>,但实际实体类名为RedisEntity,泛型类型不匹配会导致结果映射失败,查询不到数据。 - RedisTemplate序列化规则缺失:当前RedisTemplate未配置key、value的序列化规则,默认使用JDK序列化机制,会导致存储的key和你查询的字符串ID格式不匹配,即使Redis中存在对应数据也会查询为空。
- 代码笔误:测试代码中将查询结果赋值给
retrievedEntity变量,后续操作却使用了未定义的retrievedQuoteRedisEntity变量,会导致编译或运行错误。
可行解决方案
- 保证查询ID对应的数据已存在
先构造实体对象存入Redis,再用存入的ID进行查询,示例代码如下:// 先写入数据 String targetId = UUID.randomUUID().toString(); RedisEntity initEntity = new RedisEntity(targetId, 0.0); quoteRedisRepository.save(initEntity); // 再执行查询 RedisEntity retrievedEntity = quoteRedisRepository.findById(targetId).get(); - 对Optional结果做空判断,避免直接调用
get()
优先使用isPresent()判空,或使用orElse()/orElseGet()/orElseThrow()等方法处理空结果场景,示例代码如下:Optional<RedisEntity> entityOptional = quoteRedisRepository.findById(targetId); if (entityOptional.isPresent()) { RedisEntity retrievedEntity = entityOptional.get(); retrievedEntity.setPrice(10 * item / 100); quoteRedisRepository.save(retrievedEntity); } else { // 处理数据不存在的逻辑,例如新建对象存入 RedisEntity newEntity = new RedisEntity(targetId, 10 * item / 100); quoteRedisRepository.save(newEntity); } - 修正Repository泛型配置
将Repository的泛型类型替换为实际的实体类:@Repository public interface QuoteRedisRepository extends CrudRepository<RedisEntity, String> { } - 完善RedisTemplate序列化配置
给RedisTemplate设置适配的序列化规则,避免序列化不匹配导致的查询失败:@Bean RedisTemplate<String, Object> redisTemplate() { RedisTemplate<String, Object> redisTemplate = new RedisTemplate<>(); redisTemplate.setConnectionFactory(jedisConnectionFactory()); // key使用String序列化 redisTemplate.setKeySerializer(new StringRedisSerializer()); redisTemplate.setHashKeySerializer(new StringRedisSerializer()); // value使用JSON序列化 GenericJackson2JsonRedisSerializer jsonSerializer = new GenericJackson2JsonRedisSerializer(); redisTemplate.setValueSerializer(jsonSerializer); redisTemplate.setHashValueSerializer(jsonSerializer); redisTemplate.afterPropertiesSet(); return redisTemplate; } - 修正测试代码中的变量名笔误,保证变量名前后一致。
内容的提问来源于stack exchange,提问作者user1167642
相关产品推荐
相关产品推荐

