【问题标题】:What is the purpose of Spring Data and its level of Abstraction?Spring Data 的目的及其抽象级别是什么?
【发布时间】:2015-05-11 20:17:23
【问题描述】:

在尝试理解“Spring Data”的目的时,我偶然发现了这篇文章,并尝试了一些有关 Gemfire/Redis 存储库及其相应 Spring-Data 组件的示例。有人可以帮我解决以下问题。

场景: 当 GemFire 是我的数据存储时,我必须在 GemFireTemplate 上使用 create、get 和 remove 方法来执行 CRUD 操作。 当 Redis 是我的数据存储时,我必须在 RedisTemplate 上使用方法 .opsForHash().put 、 .opsForHash().get 和 .opsForHash().delete 来执行相同的 CRUD 操作。

问题

Spring-Data 不应该为 底层数据存储?如果我应该知道相应的 CRUD 方法并根据底层数据存储具有不同的 API, Spring-Data 组件引入了什么样的抽象?不能 我直接使用 Gemfire 的 Jedis 或 Java 客户端来执行这些 datatstore 特定的 CRUD 操作?

This link 似乎解释了这一点,但看起来我需要一些帮助来理解它。

没有适用于所有持久性存储的通用 API。差异太根本了。但是 Spring Data 项目确实提供了一个通用的编程模型来访问您的数据

【问题讨论】:

    标签: spring spring-data spring-data-gemfire spring-data-redis


    【解决方案1】:

    感谢您的提问,Master Slave 已经很好地指出了 Spring Data 的好处 提供是多种多样的,但有时在商店模块之间支持的功能意义上存在功能差异。那些是 部分原因是特定底层数据存储的不同特性和功能以及重点和时间限制。

    Redis 和 Gemfire 在某种程度上通过提供类似存储和访问模型的键值对类似的存储技术进行了扩展。然而,Gemfire 提供了比 Redis 更丰富的查询功能。这就是为什么 Spring Data Gemfire 的 Repository abstraction 已经有一段时间了。

    另一方面,Redis 是一个不同的故事 - 正如 Master Slave 已经提到的,您可以轻松构建自己的自定义 Redis 存储库 - 这就是 很多人都这样做——但通常与 Redis 的交互对于用例来说是非常独特的,所以我们没有看到 如此多的功能重叠激发了通用实现,而不仅仅是“保存”和“加载”。

    我们有一个 ticket 用于向 Spring Data Redis 添加存储库抽象,但我们还没有时间这样做。

    【讨论】:

    • 感谢您提供更多详细信息以及指向 Gemfire 存储库抽象。我会调查的。
    【解决方案2】:

    Spring 数据确实为底层数据存储提供了一个抽象级别。然而,NoSQL 存储是一个非常多样化的范围,一个是图形数据库,另一个是专门用于存储文档,第三个是存储键值对等。尽管如此,这些不是你想要抽象掉的差异,这些是使您首先选择它们的独特功能。

    另一方面,Spring Data 为您提供了一致性和方法,可以针对这些不同的存储应用已知模式

    • 它为您提供了一种一致的方式来配置访问商店的资源
    • 底层类型与 Java 类型之间的映射和转换
    • 大多数商店的存储库抽象归结为仅声明基本 CRUD 操作的接口。实现和特定于商店的东西由 Spring Data 处理
    • 提供回调以访问本机 API 的专用模板实现

    名单还在继续。关键是 Spring Data 确实提供了尽可能多的抽象级别,但它也没有将公开的功能限制在一个鲜为人知的共同点上,因为这会带走不同存储的好处。

    【讨论】:

    • 第一季度。 >> 这些不是您想要抽象掉的差异
    • 我相信 CRUDRepositories 可以达到这个目的,对吗?
    • 没错,CRUDRespository 是通用抽象层,在此基础上,您将获得 GemFire 和 Redis 一致的 CRUD 操作接口
    • >> 配置资源的一致方式 > 映射和转换
    • 请参阅这篇文章以了解 GemFire 实现 spring.io/guides/gs/accessing-data-gemfire,感谢 Spring Data,您可以使用 Redis 存储实现相同的目标,并且只需最少的代码重写
    【解决方案3】:

    关于这个主题的一些其他想法......

    使用 Spring 模板进行特定于数据存储的访问(例如 GemfireTemplate)的众多优势之一是,它们使开发人员免受模板通常包装的底层数据存储 API 更改的影响。如果数据存储供应商对 API 接口进行了重大更改(GemFire 就是这种情况),那么模板可以为底层 API 提供一层抽象/适应,而无需更改用户应用程序。

    此外,模板可以利用其他 Spring 基础设施管理,例如通常不会内置于底层数据存储 API 本身的事务。模板还可以为底层数据存储产品中的多个不同 API 提供外观和便利层。

    例如,GemfireTemplate 封装了“获取”和“放置”数据以及“查询”感兴趣的数据的操作。

    要在 GemFire 中执行前者,您需要执行以下操作...

    Region<String, SomeValue> example = gemfireCache.getRegion("/Example");
    
    example.put("someKey", new SomeValue(..));
    ...
    SomeValue someValue = example.get("someKey");
    

    在查询“/Example”中的数据时,您会...

    Region<String, SomeValue> example = gemfireCache.getRegion("/Example");
    QueryService queryService = example.getQueryService();
    Query query = queryService.newQuery("SELECT * FROM /Example WHERE ...");
    Object result = query.execute(<any args for query parameters>);
    
    if (result instanceof SelectResults) {
      SelectResults<SomeValue> someValues = (SelectResults) result;
      // process the query results
    }
    else {
      // figure out what happened
    }
    

    现在,将其与获取/放置数据的 Spring 模板进行对比

    gemfireTemplate.put("someKey", new SomeValue(..));
    ...
    SomeValue someValule = gemfireTemplate.get("someKey");
    

    还有查询...

    SelectResults<SomeValue> results = gemfireTemplate.find("SELECT * FROM /Example WHERE ...", args);
    
    // process the query results
    

    如果发生异常,或者无法收集结果,则 GemFires 的异常/错误会统一映射到 core Spring Framework DAO Exception hierarchy,这是另一个优势,这使得切换底层数据存储更容易,以及一致的事务处理。

    最后,虽然 Thomas Darimont 和 Master Slave 都很好地总结了使用 Spring Data Repository abstraction 的优势,但这并不是一个新概念。

    在 Spring Data 的 Repository 抽象的表达能力和便利性之前,应用程序开发人员将使用 DAO 模式从他们的应用程序服务层抽象出 CRUD 和其他数据访问操作(例如查询)。

    但是,Spring Data 为您提供的功能是通过简单地声明允许的数据访问操作的合同(Java 接口)和 Spring Data(包括提供程序特定的实现,如 Spring Data GemFire)来执行此操作其余的,插入一个“默认”数据存储特定的实现,这是高度 customizable

    显然,我是有偏见的,但是使用接口方法的名称来表示查询,使用方法的参数作为 SQL/OQL/etc 查询参数,简直是太酷了,而且功能强大。

    如果查询不复杂或不具体,这可以很容易地从一个数据存储迁移到另一个,甚至在关系和键/值存储之间(例如 GemFire,考虑到 SQL 和 OQL 之间的相似性)。

    希望这会有所帮助。干杯!

    【讨论】:

    • 这非常有帮助,尤其是在使用和不使用模板之间的代码比较......所以如果我从前面的答案中理解正确的话。理想情况下,SpringData 中的 CRUDOperations 提供了抽象,我们使用模板来访问其他底层 API。在高层次上,我可以这样概括吗?
    猜你喜欢
    • 2014-09-23
    • 2011-01-18
    • 2012-03-22
    • 1970-01-01
    • 2017-10-09
    • 2021-09-22
    • 1970-01-01
    • 2013-02-13
    • 2023-01-31
    相关资源
    最近更新 更多