原标题: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,一旦配置,就是线程安全的,并且可以跨多个应用程序类重用:
配置模板后,开发人员可以将其与GemfireCallbackApache Geode一起使用,Region而无需处理检查异常、线程或资源管理问题:
template.execute(new GemfireCallback
public Iterable doInGemfire(Region region)
throws GemFireCheckedException, GemFireException {
Region localRegion = (Region) 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
7.3.本地、缓存事务管理
Spring 框架最流行的特性之一是 事务管理。
如果你不熟悉Spring的事务抽象那么我们强烈建议您 阅读 有关Spring的事务管理的基础设施,因为它提供了一个一致的编程模型,跨多个API透明地工作,并且可以通过编程方式或声明(最流行的选择)配置。
对于 Apache Geode,Apache Geode 的 Spring Data 提供了一个专用的每个缓存
PlatformTransactionManager,一旦声明,就允许通过 Spring 原子地执行 Region 操作:
使用 XML 启用事务管理
上面的例子中,可以通过消除甚至进一步简化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 在
ClientCache XML:
使用 XML(客户端)设置读取时复制
ClientCache Java配置:
使用 JavaConfig(客户端)设置 copyOnRead
@Bean
ClientCacheFactoryBean gemfireCache() {
ClientCacheFactoryBean gemfireCache = new ClientCacheFactoryBean();
gemfireCache.setCopyOnRead(true);
return gemfireCache;
}
对等CacheXML:
使用 XML(服务器)设置读取时复制
对等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
// 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 [...]]