DAO接口只需继承CrudRepository,Spring Data Redis能为DAO组件提供实现类。 Spring Data Redis支持方法名关键字查询,只不过Redis查询的属性必须是被索引过的。 Spring Data Redis同样支持DAO组件添加自定义的查询方法—通过添加额外的接口,并为额外的接口提供实现类,Spring Data Redis就能将该实现类中的方法“移植”到DAO组件中。 Spring Data Redis同样支持Example查询。
需要说明的是,Spring Data Redis支持的方法名关键字查询功能不如JPA强大,这是由Redis底层决定的—Redis不支持任何查询,它是一个简单的key-value数据库,它获取数据的唯一方式就是根据key获取value。因此它不能支持GreaterThan
、LessThan
、Like
等复杂关键字,它只能支持如下简单的关键字。
And:比如在接口中可以定义“findByNameAndAge”。 Or:比如“findByNameOrAge”。 Is、Equals:比如“findByNameIs”“findByName”“findByNameEquals”。这种表示相同或相等的关键字不加也行。 Top、First:比如“findFirst5Name”“findTop5ByName”,实现查询前5条记录。
@RedisHash
:该注解指定将数据类映射到Redis的Hash对象。@TimeToLive
:该注解修饰一个数值类型的属性,用于指定该对象的超时时长。
@Indexed
:指定对普通类型的属性建立索引,索引化后的属性可用于查询。@GeoIndexed
:指定对Geo数据(地理数据)类型的属性建立索引。
spring-boot-starter-parent
,并添加
spring-boot-starter-data-redis.jar
依赖和
commons-pool2.jar
依赖。由于本例使用SpringBoot的测试支持来测试DAO组件,因此还添加了
spring-boot-starter-test.jar
依赖。具体可以参考本例的pom.xml文件。
application.properties
文件,用来指定Redis服务器的连接信息。
spring.redis.host=localhost
spring.redis.port=6379
# 指定连接Redis的DB1数据库
spring.redis.database=1
# 连接密码
spring.redis.password=32147
# 指定连接池中最大的活动连接数为20
spring.redis.lettuce.pool.maxActive = 20
# 指定连接池中最大的空闲连接数为20
spring.redis.lettuce.pool.maxIdle=20
# 指定连接池中最小的空闲连接数为2
spring.redis.lettuce.pool.minIdle = 2复制
@RedisHash("book")
public class Book
{
// 标识属性,可用于查询
@Id
privateInteger id;
// 带@Indexed注解的属性被称为“二级索引”,可用于查询
@Indexed
privateString name;
@Indexed
privateString description;
privateDouble price;
// 定义它的超时时长
@TimeToLive(unit = TimeUnit.HOURS)
Longtimeout;
// 省略getter、setter方法和构造器
...
}复制
@RedisHash("book")
修饰,这意味着将该类的实例映射到Redis中的key都会增加book前缀。
@Id
修饰,这表明它是一个标识属性,这一点和所有Spring Data的设计都是一样的。
@Indexed
修饰,这表明它们将会被“索引化”—其实就是为它们创建对应的key,后面会看到详细示例。
public interface BookDaoextends CrudRepository<Book, Integer>,
QueryByExampleExecutor<Book>
{
List<Book> findByName(Stringname);
List<Book> findByDescription(StringsubDesc);
}复制
CrudRepository
,这是Spring Data对DAO组件的通用要求。此外,该DAO接口还继承了
QueryByExampleExecutor
,这意味着它也可支持Example查询。
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.NONE)
public class BookDaoTest
{
@Autowired
private BookDaobookDao;
@Test
publicvoid testSaveWithId()
{
varbook = new Book("疯狂Python",
"系统易懂的Python图书,覆盖数据分析、爬虫等热门内容", 118.0);
// 显式设置id,通常不建议设置
book.setId(2);
book.setTimeout(5L); // 设置超时时长
bookDao.save(book);
}
@Test
publicvoid testUpdate()
{
// 更新id为2的Book对象
bookDao.findById(2)
.ifPresent(book -> {
book.setName("疯狂Python讲义");
bookDao.save(book);
});
}
@Test
publicvoid testDelete()
{
// 删除id为2的Book对象
bookDao.deleteById(2);
}
@ParameterizedTest
@CsvSource({"疯狂Java讲义, 最全面深入的Java图书, 129.0",
"SpringBoot终极讲义,无与伦比的SpringBoot图书, 119.0"})
publicvoid testSave(String name, String description, Double price)
{
varbook = new Book(name, description, price);
bookDao.save(book);
}
@ParameterizedTest
@ValueSource(strings= {"疯狂Java讲义"})
publicvoid testFindByName(String name)
{
bookDao.findByName(name).forEach(System.out::println);
}
@ParameterizedTest
@ValueSource(strings= {"最全面深入的Java图书"})
publicvoid testFindByDescription(String description)
{
bookDao.findByDescription(description).forEach(System.out::println);
}
@ParameterizedTest
@CsvSource({"疯狂Java讲义, 最全面深入的Java图书"})
publicvoid testExampleQuery1(String name, String description)
{
// 创建样本对象(probe)
vars = new Book(name, description, 1.0);
// 不使用ExampleMatcher,创建默认的Example
bookDao.findAll(Example.of(s)).forEach(System.out::println);
}
@ParameterizedTest
@ValueSource(strings= {"SpringBoot终极讲义"})
publicvoid testExampleQuery2(String name)
{
// 创建matchingAll的ExampleMatcher
ExampleMatchermatcher = ExampleMatcher.matching()
// 忽略null属性,该方法可以省略
//.withIgnoreNullValues()
.withIgnorePaths("description"); // 忽略description属性
// 创建样本对象(probe)
vars = new Book(name, "test", 1.0);
bookDao.findAll(Example.of(s,matcher)).forEach(System.out::println);
}
}复制
CrudRepository
和
QueryByExampleExecutor
,它们为DAO接口提供了大量方法。
testSaveWithId()
方法,该方法测试BookDao的
save()
方法,该方法运行完成后看不到任何输出。但打开
AnotherRedis DeskTop Manager
连接DB1,则可看到图1所示的数据。

@RedisHash("book")
注解,因此这些key的名字都以“book”开头。
book:标识属性值
”(此处就是book:2)的key,图2显示了该key的内容。

book:标识属性值
”key所对应的是一个Hash,它完整地保存了整个Book对象的所有数据,这就是Redis性能非常好的原因—当程序要根据id获取某个Book对象时,Redis直接获取key为“
book:id值
”的value,这样就得到了该Book对象的全部数据。
@Indexed
注解,因此Spring Data还会为它们创建对应的key,从而实现高速查找。接下来看名为“
book:name:疯狂Python
”的key的内容,可以看到如图3所示的数据。

book:name:疯狂Python
”key所对应的Set负责保存,因此该key对应的是一个Set。
@Indexed
注解修饰之后,在保存该数据对象时就会为它保存一个名为“
类映射名:属性名:属性值
”的key,在该key对应的Set中将会添加该对象的标识属性。
book:标识属性值:idx
”的内容,可以看到如图4所示的数据。

book:标识属性值:idx
”的内容也是Set,它保存该对象所有额外的key。假如程序要查找name(假设name有
@Indexed
修饰)为“疯狂Python”的图书,Spring Data Redis底层会怎么做呢?
book:name:疯狂Python
”key对应的Set,该Set中包含了所有name为“疯狂Python”的Book对象的id,然后遍历该Set的每个元素—每个元素都是一个id,接下来Spring Data Redis再获取“
book:id值
”对应的Hash对象,这样就获得了所有符合条件的Book对象。
@Indexed
修饰的Book对象,则只需要改变两个key。
book
:在该key对应的Set中添加新Book对象的id。book:id
:该key保存该Book对象的全部数据。
book
:在该key对应的Set中添加新Book对象的id。book:id
:该key对应的Hash对象保存了该Book对象的全部数据。book:id:idx
:该key对应的Set保存了该Book对象所有额外的key。N个book:属性名:属性值
:该key对应的Set保存了所有该属性都具有相同属性值的Book对象的id值。
地址:https://blog.csdn.net/weixin_42400958/article/details/118967524
复制
文章转载自猿人课堂,如果涉嫌侵权,请发送邮件至:contact@modb.pro进行举报,并提供相关证据,一经查实,墨天轮将立刻删除相关内容。
评论
相关阅读
国产非关系型数据库 Eloqkv 初体验
JiekeXu
134次阅读
2025-04-10 23:51:35
融合Redis缓存的PostgreSQL高可用架构
梧桐
91次阅读
2025-04-08 06:35:40
Redis概要
听溪
39次阅读
2025-04-11 10:23:10
Redis数据库——Cluster集群模式
编程Cookbook
34次阅读
2025-04-16 15:34:44
安装与配置Redis
鲁鲁
34次阅读
2025-04-11 10:26:10
使用Jedis访问Redis数据库
怀念和想念
29次阅读
2025-04-11 15:08:30
Redis geo 实战:“附近的人”实现,打造社交的新维度
老王两点中
28次阅读
2025-04-11 09:02:30
Redis改协议内幕曝光!核心开发者亲述被“踢出局”,外部贡献者几乎全跑光了!
老鱼笔记
27次阅读
2025-04-17 10:41:56
Redis提供的持久化机制
luyingjun
25次阅读
2025-04-11 15:11:05
Redis
鲁鲁
25次阅读
2025-04-07 20:14:35