共计 7796 个字符,预计需要花费 20 分钟才能阅读完成。
原题目:Spring 认证中国教育管理中心 -Apache Geode 的 Spring 数据教程十八(Spring 中国教育管理中心)
Spring 认证中国教育管理中心 -Apache Geode 的 Spring 数据教程十八
- 应用 Apache Geode API
一旦配置了 Apache Geode Cache 和 Regions,它们就能够被注入并在应用程序对象中应用。本章形容了与 Spring 的事务管理性能和 DAO 异样层次结构的集成。本章还介绍了对 Apache Geode 治理对象的依赖注入的反对。
7.1.Gemfire 模板
与 Spring 提供的许多其余高级形象一样,Spring Data for Apache Geode 提供了一个模板 来简化 Apache Geode 数据拜访操作。该类提供了几种蕴含常见 Region 操作的办法,但也提供了针对本机 Apache Geode API 执行代码的性能,而无需应用 GemfireCallback.
模板类须要一个 Apache Geode Region,一旦配置,就是线程平安的,并且能够跨多个应用程序类重用:
<bean id=”gemfireTemplate” class=”org.springframework.data.gemfire.GemfireTemplate” p:region-ref=”SomeRegion”/>
配置模板后,开发人员能够将其与 GemfireCallbackApache Geode 一起应用,Region 而无需解决查看异样、线程或资源管理问题:
template.execute(new GemfireCallback<Iterable<String>>() {
public Iterable<String> doInGemfire(Region region)
throws GemFireCheckedException, GemFireException {Region<String, String> localRegion = (Region<String, String>) region;
localRegion.put("1", "one");
localRegion.put("3", "three");
return localRegion.query("length < 5");
}
});
为了充分发挥 Apache Geode 查询语言的威力,开发者能够应用 findandfindUnique 办法,与办法相比 query,能够跨多个 Region 执行查问,执行投影等。
find 当查问抉择多个我的项目(通过 SelectResults)时应该应用该办法,而后者,findUnique 顾名思义,当只返回一个对象时。
7.2. 异样翻译
应用新的数据拜访技术不仅须要适应新的 API,还须要解决特定于该技术的异样。
为了适应异样解决的状况,Spring 框架提供了一个技术无关且统一的 异样层次结构,将应用程序从专有的、通常是“查看的”异样形象为一组集中的运行时异样。
正如 Spring Framework 的文档中所提到的,通过定义 bean 应用正文和 AOP,异样转换能够通明地利用于您的数据拜访对象 (DAO)。应用 Apache Geode 时,只有申明了雷同的异样转换性能,就会启用雷同的异样转换性能,例如应用 a 或申明,它充当异样转换器并由 Spring 基础设施自动检测并相应地应用。@
RepositoryPersistenceExceptionTranslationPostProcessorCacheFactoryBean<gfe:cache/><gfe:client-cache>
7.3. 本地、缓存事务管理
Spring 框架最风行的个性之一是 事务管理。
如果你不相熟 Spring 的事务形象那么咱们强烈建议您 浏览 无关 Spring 的事务管理的基础设施,因为它提供了一个统一的编程模型,跨多个 API 通明地工作,并且能够通过编程形式或申明(最风行的抉择)配置。
对于 Apache Geode,Apache Geode 的 Spring Data 提供了一个专用的每个缓存
PlatformTransactionManager,一旦申明,就容许通过 Spring 原子地执行 Region 操作:
应用 XML 启用事务管理
<gfe:transaction-manager id=”txManager” cache-ref=”myCache”/>
下面的例子中,能够通过打消甚至进一步简化 cache-ref,如果在 Apache 的 Geode 缓存下默认名称定义的属性,gemfireCache。与其余 Spring Data for Apache Geode 命名空间元素一样,如果未配置缓存 bean 名称,则将应用上述命名约定。此外,如果未明确指定,事务管理器名称为“gemfireTransactionManager”。
目前,Apache Geode 反对具备读提交隔离的乐观事务。此外,为了保障这种隔离,开发人员应防止进行手动批改缓存中存在的值的就地更改。为了避免这种状况产生,事务管理器默认将缓存配置为在读取时应用复制语义,这意味着每次执行读取时都会创立理论值的克隆。如果须要,能够通过 copyOnRead 属性禁用此行为。
因为在启用读取时复制时会复制给定键的值,因而您必须随后调用 Region.put(key, value)inorder 以事务形式更新值。
无关底层 Geode 事务管理器的语义和行为的更多信息,请参阅 Geode CacheTransactionManager Javadoc。
公共接口 CacheTransactionManager
CacheTransactionManager 接口容许应用程序在每个 Cache 根底上治理事务。
GemFire 事务的生命周期从开始操作开始。生命周期以提交或回滚操作完结。在开始和提交 / 回滚之间通常是 Region 操作。通常,那些创立、销毁、生效或更新的操作 Region.Entry 被认为是事务性的,即它们批改事务状态。
一个 GemFire 事务可能波及对多个区域的操作,每个区域可能具备不同的属性。
在本地 VM 中调用 GemFire 事务及其操作时,依据每个参加区域的属性,在提交时将生成的事务状态散发到其余 VM。
一个事务最多只能有一个与之关联的线程,相同,一个线程在任何给定工夫只能对一个事务进行操作。子线程不会继承现有事务。
以下每个办法都在以后线程上运行。CacheClosedException 如果 Cache 敞开,则所有办法都会抛出。
GemFire Transactions 目前只反对 Read Committed 隔离。此外,它们是乐观事务,因为写锁定和抵触查看是作为提交操作的一部分执行的。
为了保障读已提交隔离,防止进行“就地”更改,因为此类更改将被其余事务“看到”并毁坏读已提交隔离保障。例如
CacheTransactionManager txMgr = cache.getCacheTransactionManager();
txMgr.begin();
StringBuffer s = (StringBuffer) r.get(“stringBuf”);
s.append(“ 提交前看到的更改。未提交读取!”);
r.put(“stringBuf”, s);
txMgr.commit();
为了帮忙创立正本,提供了“读取时复制”Cache 属性和 CopyHelper.copy(T)办法。以下是应用该 CopyHelper.copy 办法的 Read Committed 平安示例。
CacheTransactionManager txMgr = cache.getCacheTransactionManager();
txMgr.begin();
Object o = r.get(“stringBuf”);
StringBuffer s = (StringBuffer) CopyHelper.copy(o);
s.append(“ 提交前未见更改。已提交读取。”);
r.put(“stringBuf”, s);
txMgr.commit();
须要留神的是,创立正本会对性能和内存耗费产生负面影响。
反对分区区域、分布式无确认和分布式确认区域(参见 AttributesFactory 范畴)。对于这两个范畴,强制执行统一的配置(每个 VM)。
全局区域、客户端区域(参见 org.apache.geode.cache.client 包)和长久区域(参见 参考资料 DiskWriteAttributes)不反对事务。
当 PartitionedRegions 参加到一个事务中时,事务中的所有数据必须独特位于一个数据节点上。无关在分区区域中应用事务的详细信息,请参阅 GemFire 开发人员指南。
7.4. 全局,JTA 事务管理
Apache Geode 也能够参加基于 JTA 的全局事务,例如由 Java EE 应用服务器(例如 WebSphere 应用服务器(WAS))应用容器治理事务(CMT)和其余 JTA 资源管理的事务。
然而,与许多其余 JTA“兼容”资源(例如,像 ActiveMQ 这样的 JMS 音讯代理)不同,Apache Geode 不是 XA 兼容资源。因而,Apache Geode 必须被定位为 JTA 事务(筹备阶段)中的“最初一个资源”,因为它没有实现两阶段提交协定,或者更确切地说,它不解决分布式事务。
许多反对 CMT 的托管环境在基于 JTA 的事务中保护对“最初资源”、非 XA 兼容资源的反对,只管 JTA 标准实际上并不需要它。无关不合乎 XA 的“最初资源”的含意的更多信息能够在 Red Hat 的文档中找到。事实上,Red Hat 的 JBoss 我的项目 Narayana 就是这样一种 LGPL 开源实现。Narayana 将此称为“最初资源提交优化”(LRCO)。能够在此处找到更多详细信息。
然而,无论您是在具备反对“最初资源”的开源 JTA 事务管理实现的独立环境中应用 Apache Geode,还是在托管环境(例如 Java EE AS,如 WAS)中应用 Apache Geode,Apache Geode 的 Spring Data 都能满足您的需要。
您必须实现一系列步骤能力在波及 1 个以上事务资源的 JTA 事务中正确应用 Apache Geode 作为“最初一个资源”。此外,在这种安顿中只能有 1 个非 XA 兼容资源(例如 Apache Geode)。
1) 首先,您必须在此处实现 Apache Geode 文档中的步骤 1-4。
下面的 #1 独立于您的 Spring [Boot] 和 / 或 [Data for Apache Geode] 应用程序,并且必须胜利实现。
2) 参考 Apache Geode 文档中的第 5 步,Spring Data for Apache Geode’s Annotation support 将尝试 在应用正文时为您设置 GemFireCache,copyOnRead 属性 @
EnableGemFireAsLastResource。
然而,如果 SDG 在这方面的主动配置不胜利,那么您必须 copy-on-read 在 <gfe:cache> 或 <gfe:client-cache>XML 元素中显式设置该属性或将 JavaConfigcopyOnRead 中的 CacheFactoryBean 类的属性设置为 true。例如:
ClientCache XML:
应用 XML(客户端)设置读取时复制
<gfe:client-cache … copy-on-read=”true”/>
ClientCache Java 配置:
应用 JavaConfig(客户端)设置 copyOnRead
@Bean
ClientCacheFactoryBean gemfireCache() {
ClientCacheFactoryBean gemfireCache = new ClientCacheFactoryBean();
gemfireCache.setCopyOnRead(true);
return gemfireCache;
}
对等 CacheXML:
应用 XML(服务器)设置读取时复制
<gfe:cache … copy-on-read=”true”/>
对等 Cache JavaConfig:
应用 JavaConfig(服务器)设置 copyOnRead
@Bean
CacheFactoryBean gemfireCache() {
CacheFactoryBean gemfireCache = new CacheFactoryBean();
gemfireCache.setCopyOnRead(true);
return gemfireCache;
}
显式设置 copy-on-read 属性或 copyOnRead 属性实际上是没有必要的。启用事务管理须要在读取时进行复制。
3) 此时,您能够跳过 Apache Geode 文档中的步骤 6-8,让 Spring Data Geode 施展其魔力。您须要做的就是 @Configuration 应用 Spring Data for Apache Geode 的新 @
EnableGemFireAsLastResource 注解来注解您的 Spring 类,并且 Spring 的 事务管理基础设施和 Spring Data for Apache Geode 的 @EnableGemFireAsLastResource 注解配置的组合就能够解决问题。
配置看起来像这样 ……
@Configuration
@EnableGemFireAsLastResource
@EnableTransactionManagement(order = 1)
class GeodeConfiguration {
…
}
惟一的要求是……
3.1)@
EnableGemFireAsLastResource 注解必须在指定 @ConfigurationSpring@EnableTransactionManagement 注解的同一个 Spring 类上申明。
3.2)正文的 order 属性 @
EnableTransactionManagement 必须显式设置为整数值,不是 Integer.MAX_VALUE 或 Integer.MIN_VALUE(默认为 Integer.MAX_VALUE)。
当然,心愿你晓得 JtaTransactionManager 在应用 JTA 事务时你还须要配置 Spring 的。
@Bean
public JtaTransactionManager transactionManager(UserTransaction userTransaction) {
JtaTransactionManager transactionManager = new JtaTransactionManager();
transactionManager.setUserTransaction(userTransaction);
return transactionManager;
}
在节中的配置本地,缓存事务管理并没有实用于此。Spring Data for Apache Geode 的应用 GemfireTransactionManager 实用于“仅限本地”、缓存事务,而不是“全局”、JTA 事务。因而,在这种状况下不配置 SDG GemfireTransactionManager。您 JtaTransactionManager 如上所示配置 Spring。
无关将 Spring 的事务管理与 JTA 联合应用的更多详细信息,请参见此处。
实际上,Spring Data for Apache Geode 的 @
EnableGemFireAsLastResource 注解导入了蕴含 2 个 Aspect bean 定义的配置,这些定义在事务操作期间的适当点解决 Apache Geodeo.a.g.ra.GFConnectionFactory.getConnection() 和 o.a.g.ra.GFConnection.close()操作。
具体来说,正确的事件程序如下:
jtaTransation.begin()
GFConnectionFactory.getConnection()
调用应用程序的 @Transactional 服务办法
无论是 jtaTransaction.commit()或 jtaTransaction.rollback()
最初,GFConnection.close()
这与您作为应用程序开发人员在必须本人应用 JTA API + Apache Geode API 时手动编码的形式统一,如 Apache Geode 示例 所示。
值得庆幸的是,Spring 为您实现了沉重的工作,在利用适当的配置(如上所示)后,您须要做的就是:
将服务办法申明为 @Transactional
@Service
class MyTransactionalService {
@Transactional
public <Return-Type> someTransactionalServiceMethod() {
// perform business logic interacting with and accessing multiple JTA resources atomically
}
…
}
PlatformTransactionManager 一旦 @Transactional 您的应用程序进入边界(即 MyTransactionService.someTransactionalServiceMethod() 调用时),下面的 #1 和 #4 就会由基于 Spring 的 JTA 适当地解决。
2 和 #3 由 Spring Data 解决,用于启用 @
EnableGemFireAsLastResource 正文的 Apache Geode 的新方面。
3 当然是你的应用程序的责任。
事实上,通过配置适当的日志记录,您将看到正确的事件序列 ……
事务日志输入
2017-Jun-22 11:11:37 TRACE TransactionInterceptor – Getting transaction for [example.app.service.MessageService.send]
2017-Jun-22 11:11:37 TRACE GemFireAsLastResourceConnectionAcquiringAspect – Acquiring {data-store-name} Connection
from {data-store-name} JCA ResourceAdapter registered at [gfe/jca]
2017-Jun-22 11:11:37 TRACE MessageService – PRODUCER [Message :
[{@type = example.app.domain.Message, id= MSG0000000000, message = SENT}],
JSON : [{“id”:”MSG0000000000″,”message”:”SENT”}] ]
2017-Jun-22 11:11:37 TRACE TransactionInterceptor – Completing transaction for [example.app.service.MessageService.send]
2017-Jun-22 11:11:37 TRACE GemFireAsLastResourceConnectionClosingAspect – Closed {data-store-name} Connection @ [Reference […]]